home *** CD-ROM | disk | FTP | other *** search
/ LSD Docs / LSD Docs.iso / FILEZ / lsd28.dms / lsd28.adf / AmigaCBeginners.2.doc.pp / AmigaCBeginners.2.doc
Text File  |  1990-09-07  |  168KB  |  4,484 lines

  1.                         CHAPTER 19 - COMPLEX DATA TYPES.
  2.  
  3. Now that we've listed all the important commands, we now come to the extra
  4. capabilities of C. Among these are data types which can be configured
  5. according to the demands and need of the user.
  6.  
  7.  
  8. 19.1 STRUCT.
  9.  
  10.         struct {
  11.         char firstname[20];
  12.         char surname[30];
  13.         int age;
  14.         double income;
  15.         int sex;
  16.         } person;
  17.  
  18. The PERSON variable.
  19.  
  20. This function defines the variable person. The variable person consists of
  21. several partial variables which are described in more details within the
  22. braces. The first name has 20 characters, and the last name 30 characters.
  23. There are also fields for age, income and sex. Similar to arrays, many
  24. entries are collected under one name. The difference is that different
  25. variable types appear within the structure. Accessing individual parts of
  26. this variable requires more specification than arrays, which use an index.
  27. The structure uses either the . (period) operator or -> operator. An
  28. assignment of 30 to the element age appears as follows:
  29.  
  30.         person.age = 30;
  31.  
  32. All other fields an be accessed in the same manner:
  33.  
  34.         person.sex = 0;
  35.         person.income = 300000.0;
  36.         strcpy(person.firstname, "Rena");
  37.         strcpy(person.surname, "Bebewicz");
  38.  
  39. In order to use a pointer on such a construction, you must indicate the
  40. data types. All youve done so far is to create a complete variable. You
  41. need a name such as INT or FLOAT, through which other variables such as a
  42. pointer can be defined. If several variables or pointers are used, it would
  43. be better to create another data type which also has it's own name. This
  44. can be done by indicating the type name after the STRUCT statement. If it
  45. is called PERSON, the uppercase letter indicates that it isn't a variable.
  46. Since variables, statements and functions must appear in lowercase letters,
  47. and defines in uppercase and lowercase letters, structures can use a
  48. combination of the two:
  49.  
  50.         struct Person {
  51.                 char firstname[20];
  52.                 char surname[30];
  53.                 int age;
  54.                 double income;
  55.                 int sex;
  56.                 } person;
  57.  
  58. A pointer to this structure can now be initialised for access:
  59.  
  60.         struct Person *pointer;
  61.  
  62. To acces one element of the structure the expression would be:
  63.  
  64.         (*pointer).age = 30;
  65.  
  66.  
  67. POINTER OPERATORS :
  68.  
  69. The parenthesis above control the higher precedence of the (.) operrator.
  70. Usually a special operator is used as illustrated below:
  71.  
  72.         pointer->age = 30;
  73.  
  74.  
  75. This operator, made of a minus sign and a greater than character, is easier
  76. to read. In addition, the arrow better illustrates it's purpose (it "points
  77. to" something).
  78.  
  79. All operators which affect basic data types, such as defining arrays
  80. (vectors), can be used on the newly created structure. The line below
  81. provides 100 structures for storing partial variables:
  82.  
  83.         struct Person occupant[100], *occ_upa;
  84.  
  85. Addressing individual entries can be done through an index
  86. (oppupant[3].income = 25000.00), or after initialising the pointer with :
  87.  
  88.         occ_upa = occupant;
  89.  
  90. COMMENT : The name represents the address of the first element. The
  91. following could be written as an alternative :
  92.  
  93.         occ_upa = &occupant[0];
  94.  
  95. The pointer can also be used to access the entries :
  96.  
  97.         (pointer->income = 25000.00)
  98.  
  99. The pointer can be used to search the entire array. The following example
  100. sets the pointer to the first free elements, provided that in an unused
  101. entry the value zero was stored in AGE :
  102.  
  103.         while(pointer->age)
  104.             pointer++;
  105.  
  106. Further applications of the struct directive will be discussed later.  
  107.  
  108.                                 PAGE 174
  109.  
  110. -----------------------------------------------------------------------------
  111.  
  112.  
  113. 19.2 BIT FIELDS.
  114.  
  115. The last remaining data type is the BIT FIELD. Bit fields are really a form
  116. of structure definition. Unlike regular definitions, bit fields are usually
  117. taken apart rather than created. A variable is defined which consists of a
  118. certain number of bits. This variable always represents whole numbers. The
  119. value range depends on the number of bits used. This number can be
  120. calculated with the formula 2**number_of_bits. These fields are arranged in
  121. INT objects so that the maximum field width is 16 bits. This also applies
  122. to Lattice C which usually has a different concept of INT. If a field
  123. doesn't fit into the partially occupied integer value, it goes into the
  124. next one. A lot of memory can be saved by clever selection of the field
  125. width.
  126.  
  127.         struct {
  128.                 unsigned sex : 1;
  129.                 unsigned married : 1;
  130.                 unsigned children : 4;
  131.                } data;
  132.  
  133.  
  134. As in other structure definitions, the data types are placed inside braces.
  135. to ensure that the bit field contains unsigned whole numbers, unsigned is
  136. used (an abbreviation for unsigned int). A colon separates the field name
  137. from the field width in bits. The definition above occupies two bytes (
  138. size of a 16-bit integer), but this is not completely utilised. Since only
  139. 6 bits are used (1+1+4), an additional 10 bits can be assigned for other
  140. applications without requiring additional memory:
  141.  
  142.         struct {
  143.                 unsigned sex : 1;
  144.                 unsigned married : 1;
  145.                 unsigned children : 4;
  146.                 unsigned age : 7;
  147.                 unsigned nr_cars : 3;
  148.                 } data;
  149.  
  150. Additional data hass been stored which only occupies 2 bytes. Access to
  151. each bit field occurs with the (.) operator.
  152.  
  153.         data.children = 2;
  154.  
  155. The limited values must be respected, since in this definition no family
  156. can have more than 15 children or operate more than 7 cars.
  157.  
  158.                                 PAGE 175
  159.  
  160. ----------------------------------------------------------------------------
  161.  
  162. 19.3 UNIONS.
  163.  
  164. A special variable exists in C which accepts all conceivable data types.
  165. This UNION is dimensioned by the compiler in a way that allows it to accept
  166. all data types indicated in the definition :
  167.  
  168.         Union universa {
  169.                 int i;
  170.                 double d;
  171.                 struct Person;
  172.                 char c[100];
  173.                 } result;
  174.  
  175. All data types indicated can be stored in RESULT. It is useful to remember
  176. what type is stored, for example :
  177.  
  178.         result = 2.8;
  179.  
  180. or
  181.         strcpy(&result,c);
  182.  
  183. The memory requirements of such a variable depends of course on the length
  184. of the largest entry. In the example above this would be 100 bytes used by
  185. array C. Please note that only one type can be stored in this variable. The
  186. author hasn't yet found a reason for using UNION structures instead of
  187. solving the problem with other C data types.
  188.  
  189.                                 PAGE 176
  190.  
  191. ----------------------------------------------------------------------------
  192.  
  193. 19.4 ENUM.
  194.  
  195. The C word ENUM defines a data type which assigns constant values to the
  196. variables. Short for ENUMeration, ENUM lets you assign a consistent integer
  197. number (constant) to a variable. This is useful for assigning numbers to
  198. strings. The following example assigns numbers to the first three words in
  199. COLOR and a specific value to the BLACK variable. Finally, the assignement
  200. to the WHITE variable continues where the number assigned to BLACK left
  201. off:
  202.  
  203.         /* Definition of such a Data Type */
  204.         enum color(red,green,blue,black = 9,white)
  205.  
  206.         /* Variable definition */
  207.  
  208.         enum color var, *color_ptr = &var;
  209.  
  210.         var = blue
  211.         if(*color_ptr == green)
  212.            *color_ptr == black;
  213.  
  214. The ENUM type assigns an integer value to each name starting at zero and
  215. adding one for each element. With direct assignment values can be skipped.
  216. The values defined in COLOR are :
  217.  
  218.         red     0
  219.         green   1
  220.         blue    2
  221.         black   9
  222.         white   10
  223.  
  224.  
  225.                                 PAGE 177
  226.  
  227. ----------------------------------------------------------------------------
  228.  
  229. 19.5 TYPEDEF.
  230.  
  231. The TYPEDEF feature can be used to create new data names. A name assigned
  232. with this command can be used as another data type during the definition.
  233. The program below gives the word FLOAT the same meaning as the double data
  234. type:
  235.  
  236.         typedef double FLOAT;
  237.  
  238. The advantage of this directive is that TYPEDEF permits changes in the
  239. entire program similar to define. Also large data types can be abbreviated
  240. with this command. Look at the example below:
  241.  
  242.         typedef char * STRING;
  243.  
  244. All pointer to char elements can be defined simply with the word STRING.
  245. The typedef command has an advantage over the #define directive in that the
  246. definition of the replacement occurs in a different way. One text can be
  247. replaced with another text. A blank marks the spot in which the text
  248. replacement appears. The redefinition of type STRING into another word
  249. isnt possible since everything after the space behind CHAR already counts
  250. as replacement text. With the TYPEDEF command this is just the reverse. The
  251. last string STRING is the replacement type for the data type char*. It or
  252. the blanks in the middle always belong to the definition of the data type.
  253.  
  254. This concludes the introduction to C keywords. These statements can now be
  255. used in smaller programs. Practise make perfect. Experiment by changing one
  256. or more parameters in the programs to determine the effect upon the
  257. program. Write your own new programs once you've gotten use to entering the
  258. ones already listed above.
  259.  
  260.  
  261.                                 PAGE 178
  262.  
  263. ----------------------------------------------------------------------------
  264.     
  265.                    CHAPTER 20 - IMPORTANT CONCEPTS.
  266.  
  267. 20.1 DECLARATIONS.
  268.  
  269. Declarations declare the data type of a variable or function in a program. 
  270. Varaious declarations have already been used. Directives can appear in which
  271. you have to guess the data type that was declared, unless you examine the 
  272. expression for certain rules. First, some simple examples (the first 3 are 
  273. also definitions).
  274.  
  275.     int i;            Integer variable.
  276.     float array[20];     float variable.
  277.     double *ptr;        Pointer to double element.
  278.     long func();        Function which returns a long value.
  279.  
  280. Every declaration basically contains an elementary data type (char,int,
  281. float) which in certain case can be augmented by a special storage class
  282. (auto, extern, register, static), or through attributes such as long,
  283. short and unsigned.
  284.  
  285.     extern doulbe sin();    Function from another file.
  286.                 returns double value.
  287.  
  288.     static short digit;    Small integer variable.
  289.     register long i;    Long-variable stored in a register.
  290.  
  291. Each name can also be equipped with combinations of *, [] or even (). The
  292. asterisk to the left of the name represents the pointer character. 
  293. Parenthesis and brackets appear to the right of the name. They should not 
  294. contain values during declaration, because that turns the declaration into 
  295. a definition ([] for array and () for functions). Combining all parts of a 
  296. declaration can result in some complicated combinations :
  297.  
  298.     long *field();        function which returns pointer to a 
  299.                  long value.
  300.  
  301.     int *i_ptr[];        Field of integer pointers.
  302.     float(*berech)();    Pointer to function which returns float value
  303.                     
  304.     char *(*text)();    Pointer to function which returns pointer to
  305.                 char.
  306.  
  307.     int *(*text_arr[])();    Array of pointers to functions which return 
  308.                 pointers to int.
  309.  
  310.                 PAGE 181
  311.  
  312. ----------------------------------------------------------------------------
  313.  
  314. Complicated expressions are formed with unified rules. Going through them 
  315. step by step makes the routine work later to decode such combiniations.
  316. Youll need the table of operator precedence found in the Appendices. From
  317. this can see that the parenthesis have higher priority than the pointer.
  318.  
  319. Look at the first example listed above :    
  320.  
  321.     long *field();
  322.  
  323. DECODING EXPRESSIONS.
  324.  
  325. First, the variable FIELD is a function. Look at the left side of the line
  326. for the asterisk which defines the expression as a function. This function 
  327. returns a pointer. No additional information exists beyond the parenthesis.
  328. The left side of the line identifies the data type LONG. Together this 
  329. information create a function which returns a pointer to the type LONG.
  330.  
  331. After processing one side of the line, the information to the right of it 
  332. must be processed (if priorities permit). The last and most complex example
  333. look like this :
  334.  
  335.     int *(*text_arr[])();
  336.  
  337. It looks complicated. It can be easily decoded by following the procedures
  338. listed above, but the description will take a little longer.
  339.  
  340. Start with the name text_Arr. First test which operators are processed 
  341. first according to priority (to the right or left of the name). These are
  342. the brackets which indicate an array. The operator has been processed on 
  343. the right, now go to the left. A pointer there indicates that this is a 
  344. pointer array. The right side of the line informs you that the pointers 
  345. should point to functions (the parenthesis are required because of the high
  346. priority of parenthesis over the asterisk). Changing sides again, you note
  347. that the function returns pointers. Since on the right side there is no 
  348. additional information, continue on the left with the data type. There it 
  349. shows that the pointers point to integers. This line declares an array of 
  350. pointers to functions which return pointers to INT. Complicated expression,
  351. complicated sentence; but simple to analyse.
  352.  
  353. Only data types which cannot be used in definitions as values for passing are
  354. prohibited. For example, not function can be declared which should pass
  355. structures, arrays or functions. Pointers to such objects are permitted and 
  356. are the only way to access this information.
  357.  
  358.                 PAGE 182
  359.  
  360. ---------------------------------------------------------------------------
  361.  
  362. COMMENT :
  363.  
  364. Some new compilers also permit stucture passing. This may differ from one 
  365. compiler to another. The expression &structure is always the address of the
  366. structure, but STRUCTURE can represent different things. In the older 
  367. compilers this represents that starting address, like the expression with 
  368. the address operator. If structure is passed with a compiler that can already
  369. pass the data structure,the entire data field is made available to the calling 
  370. function (not just the 4 bytes which represent the pointer to it).
  371.  
  372.                 PAGE 183
  373.  
  374. ------------------------------------------------------------------------------
  375.  
  376. 20.2 INITIALISATION.
  377.  
  378. This word should also look familiar from earlier chapters. Before you continue
  379. here's a brief reminder of what initialisation does.
  380.  
  381. This expression designates the first value assignment of a variable. Before 
  382. using a variable it must contain a defined value. Otherwise the result of 
  383. calculations may be nonsense, or the system may crash. The initialisation can
  384. be a direct assignment in the following form:
  385.  
  386.     int i;
  387.     i = 0;
  388.  
  389. Or condensed into one line :
  390.  
  391.     int i = 0;
  392.  
  393. The initialisation in the definition has the advantage of not requiring 
  394. additional assignments to set the variable. This saves time and memory.
  395. Declarations, definitions and initialisations can be combined with one
  396. data type :
  397.  
  398.     double number, pi=3.1415926, sin();
  399.  
  400. C permits any constants and expressions during the initialisation. The 
  401. following assignments can be found in one line :
  402.  
  403.     long number = x * pi - abs(y);
  404.     char *cp = string + strlen(string);
  405.  
  406. The variables used were already initialised or NUMBER would have contained 
  407. an undefined value.
  408.  
  409. Braces can improve visibility for arrays and structures, and separate 
  410. individual entries from each other. A pair of braces must be places before
  411. and after the data which are to be transferred to the variables. A comma
  412. follows the fields, even if the braces were used. After initialisation there
  413. is a semicolon which is often omitted, causing compiler errors. Some examples
  414. for correct structure definition:
  415.  
  416.     struct CAR {
  417.         char make[16];
  418.         int hp;
  419.         int cylinder;
  420.         double price;
  421.         };
  422.  
  423.     struct CAR will_have = 
  424.         {
  425.          "bmw",
  426.         120,
  427.         4,    
  428.         40000.00    
  429.         };
  430.  
  431.                 PAGE 184
  432.  
  433. -----------------------------------------------------------------------------
  434.  
  435. Or collected together throught the structure definition:
  436.  
  437.     struct CAR = {
  438.             char make[16];
  439.             int hp;
  440.             int cylinder;
  441.             double price;
  442.              } will_have = 
  443.     {
  444.        "bmw",    
  445.        120,
  446.        4,
  447.        40000.00
  448.     };
  449.  
  450. The examples of multi-dimensional array initialisation were already discussed 
  451. in the chapter about arrays and pointers. Limitiations because of memory 
  452. classed were also mentioned. Initialisation is only permitted for Global,
  453. external or static variables. If an auto variable appears within a function
  454. which corresponds to this initialisation e.g.:
  455.     
  456.     char message[] = "Remember the initialisation!";
  457.  
  458. This can be fixed with a pointer definition:
  459.  
  460.     char *message[] = "Remember the definition!";
  461.  
  462. There are no limitations if the lower definition is used as a pointer 
  463. variable. Another possibility is the use of STATIC variables. It doesn't 
  464. matter whether the string is stored in a STATIC or AUTO variable. One small
  465. word but a big difference.
  466.  
  467.     static char message[] = "Remember the Initialisation!";
  468.  
  469.                 PAGE 185
  470.  
  471. ----------------------------------------------------------------------------
  472.  
  473.             CHAPTER 21 - POINTER ARRAYS.
  474.  
  475. You worked with pointers and arrays in earlier chapters. As the title 
  476. indicates they can be combined to construct an array of pointers. You may be
  477. wondering what you can do with a pointer array. If you marketed an existing 
  478. program in a foreign country, youd have to find every piece of text in the
  479. source code and translate the text into that foreign language. It would be 
  480. simpler and safer to store all the text in one area of the program or even 
  481. in a separate file, and let the translator change it from there. A pointer 
  482. array would point toward that area or file.
  483.  
  484. Lets start with a list of error message that the user might see after entering
  485. incorrect input. The use of error numbers makes sense, since some errors occur
  486. at several different locations. In the current program portion passign the
  487. error number to the error routine is sufficient because the function should
  488. do the rest.
  489.  
  490. One solution to this problem would be a function that tests the occurence of 
  491. this error or another error, and displays a message if necessary.
  492.  
  493.     error(e_number)
  494.     int e_number;
  495.     
  496.     {
  497.       switch(e_number)
  498.         {
  499.         case 0:
  500.            puts("Everything OK, no error!");
  501.            break;
  502.         case 1:
  503.            puts("wrong key activated!");
  504.            break;
  505.         case 2:
  506.            puts("Please insert Diskette!");
  507.            break;
  508.         default:
  509.            puts("Unknown error occurred!");
  510.        }
  511.     }
  512.  
  513.  PUTS:
  514.  
  515. This is a faitly complex implementation of a function which requires another
  516. PUTS call for each additional error message. The PUTS function displays a 
  517. string on the monitor, without the options available in PRINTF. It is a 
  518. litte faster than the general output function, but various CASE statements 
  519. must be added, which slow down the program. Since every number can be
  520. assigned a certain error message (string), it should be possible to use the 
  521. error number as an index to a field of strings. Since a string is usually
  522. stored in char error[81], the memory for the text is defined as a 2 
  523. dimensional array :
  524.  
  525.     char error[32][81];
  526.  
  527.                 PAGE 189
  528.  
  529. -----------------------------------------------------------------------------
  530.  
  531. Now there is space for 32 strings with a maximum length of 81 characters each.
  532. This formulation permits the following routine for error message output:
  533.  
  534.     error(e_number)
  535.     int e_number;
  536.  
  537.     {
  538.        puts(error[e_number]);
  539.     }
  540.  
  541. But the work which was saved here must be completed elsewhere. Each string 
  542. must be initialised with the STRCPY function. The following command sequence
  543. shows how:
  544.  
  545.     strcpy(error[0],"Everything Ok, no error!");
  546.     strcpy(error[1],"Wrong key Pressed!");
  547.     strcpy(error[2],"Please Insert Diskette");
  548.  
  549. It doesnt matter whether text is called with STRCPY or PUTS. A disadvantage 
  550. of this method is that memory gets allocated elsewhere. The definition 
  551. allocates 81 characters, including a null byte for every error message 
  552. even if a message only requires 20 bytes. This doesnt matter too much in 
  553. the Amiga but the user shouldn't develop bad programming habits. If you do
  554. the same thing for a text in which each word is assigned an entry, memory 
  555. rapidly fills with garbage.
  556.  
  557. As a last resort, the string arrays can solve almost all the problems 
  558. mentioned above. The definition of a string array is as follows:
  559.  
  560.     char *error[32];
  561.  
  562. The pointer can be set to the beginning of an error message and can make the 
  563. message length dependant on a fixed array length. The next string starts
  564. immediately after the last character of the previous string. This avoids 
  565. initialisation.
  566.  
  567. You may remember that a program in chapter 15 pointed to a string within 
  568. program text. This can occur during pointer definition; the entire pointer 
  569. array is initialised with the starting addresses of the strings. The error 
  570. messages must be defined a GLOBAL if this turns out to be the case:
  571.  
  572.     /* error_msg.c 21 */
  573.     char *error[] = 
  574.     {
  575.        "Everything Ok, no error!",
  576.        "Wrong key activated!",
  577.        "Please Insert Diskette"
  578.     };
  579.  
  580.  
  581.                 PAGE 190
  582.  
  583. -----------------------------------------------------------------------------
  584.  
  585.     main()
  586.     {
  587.       /* DISPLAY ALL ERROR MESSAGES */
  588.       int i, error_msg = sizeof(error) / sizeof(char*);
  589.  
  590.       for(i=0; i<error_msg; i++)
  591.        printf("Error Number %d: \"%s\"\n",i, error[i]);
  592.     }
  593.  
  594. Since the number of error messages are not counted, they aren't indicated
  595. during the definition. Because of this, additional text can be entered 
  596. between the braces without making changes. In the actual program, however,
  597. the number must be calculated. The memory requirement of ERROR can be 
  598. obtained from SIZEOF. The ERROR function is now an array of pointers. Now
  599. SIZEOF reports that the variable consumes 12 bytes. That is the memory 
  600. requirement for any pointer, and has no bearing on the memory needed for 
  601. the text. The 12 bytes are divided by the space requirement of a char 
  602. pointer (which is 4 bytes). The result is the number of pointers, the
  603. maximum index minus one (the indexes start with 0).
  604.  
  605.                 PAGE 191
  606.  
  607. ----------------------------------------------------------------------------
  608.  
  609.             CHAPTER 22 - USEFUL MACROS.
  610.  
  611. Much work has already been done with #define. The substituted text called a 
  612. macro, was kept simple; one word exchanged for another. But that's only half
  613. the job, macros also allow you to pass arguments. Some useful macros have 
  614. been developed to make parameter passing easier for the user.
  615.  
  616. CONSTITUTION OF A MACRO :
  617.  
  618. Functions that do little and have concise coding can be written as macros.
  619. Since macros replace the original text, the compiler translates the C code
  620. directly to machine language at that location. Function calls or parameter
  621. passing is not required. The required directives are located at the exact 
  622. location in the program. This makes the macros faster and more efficient than
  623. the function calls. If used frequently, however, macros make the program code
  624. much larger. The same operations are repeatedly stored in identical form at 
  625. the exact place where they are needed in the program code. An advantage of 
  626. macros is that they are usually independant of data types. This condition
  627. can be seen in the example of the MAX macro created earlier in the 
  628. book :
  629.  
  630.     #define MAX(a,b) ((a>b)? a:b)
  631.  
  632. If variables i1 and i2 have been defined as integers, the following macro
  633. results :
  634.         
  635.     result = MAX(i1,i2);
  636.  
  637. From the preprocessor :
  638.  
  639.     result = ((i1>i2)? i1 : i2);
  640.  
  641. The variable result is also an integer value. If i1 and i2 were defined as
  642. FLOAT values, the same expression occurs, but a float number is returned
  643. for result. In text replacement it doesn't matter which data type was used.
  644. This is impossible with functions because the data types are specified for 
  645. parameters that are passed. This is extremely easy to use.
  646.  
  647.                 PAGE 195
  648.  
  649. ----------------------------------------------------------------------------
  650.  
  651. 2.2.1 MACRO ERROR SOURCES.
  652.  
  653. Improperly implemented macros harbour some dangers which can lead to errors.
  654. These errors can be extremely difficult to detect, but most can be prevented
  655. with little effort.
  656.  
  657. If the macro call just defined included some parameters which contained 
  658. operators, errors could appear. For example :
  659.  
  660.     result = MAX(i1 / 2, i2);
  661.  
  662. is converted as usual into :
  663.  
  664.     result = ((i1 / 2 > i2)? i1 : i2);
  665.  
  666. The > comparison operator has a higher precedence than the | character. This
  667. means that first a test is made to see whether i2 is less than 2. The result
  668. of this logical comparison (1=TRUE , 0=FALSE) is then combined with i1 using
  669. OR bit by bit. This could not occur in the basic calculations since they have
  670. a higher precedence than the comparison operators (see Appendices for a table
  671. of all precedences). A simple remedy is to place all parameters found in the 
  672. macro inside parenthesis. Use this definition :
  673.  
  674.     #define MAX (a,b)  (((a)>(b))? (a) : (b))
  675.  
  676. Side-effects caused by calculations and value changes can also cause problems.
  677. A simple example is the following short program which should calculate the 
  678. squares of numbers between 0 to 10.
  679.  
  680.     /* bad_macro.c  22.1  */
  681.  
  682.     #define QUADRAT(x) ((x)*(x))
  683.  
  684.     main()
  685.     {
  686.        /* Wrong use of a macro */
  687.        int i = 0;
  688.        while(i<=10)
  689.         {
  690.         printf("The square of %d ",i);
  691.             printf("is %d\n",QUADRAT(i++));
  692.         }
  693.     }
  694.  
  695. The output of the program is :
  696.  
  697.     The square of 0 is 0
  698.     The square of 2 is 6
  699.     The square of 4 is 20
  700.     The square of 6 is 42
  701.     The sqaure of 8 is 72
  702.     The square of 10 is 110
  703.  
  704.                 PAGE 196
  705.  
  706. ----------------------------------------------------------------------------
  707.  
  708. Wheres the mistake?. Examine the material left by the preprocessor for the 
  709. compiler. The line with the macro is the important line:
  710.  
  711.     printf("is %d\n",QUADRAT(i++));
  712.  
  713. It becomes :
  714.  
  715.     printf("is %d\n",((i++)*(i++)));
  716.  
  717. If the square of 2 (i=2) is computed, the following expression is what was
  718. calculated and passed to the PRINTF function:
  719.  
  720.     2 * 3
  721.  
  722. The variable is incremented BEFORE the multiplication, and the second 
  723. multiplier is wrong.
  724.  
  725. You may have wondered why the program uses two printf calls instead of making
  726. do with one. There is another error source here which must be considered as
  727. a separate entity, otherwise this overview would not cover all possible side
  728. effects. To demonstrate the errors which occur in printf functions, lets try
  729. this with same function, but without a macro:
  730.  
  731.     main()
  732.     {
  733.        /* Wrong use of a macro   */
  734.        int i = 0;
  735.        while (i<=10)
  736.        {
  737.          printf("The square of %d is %d\n",i,i * i++);
  738.        }
  739.  
  740. As a result you get two squared numbers which dont match the desired numbers.
  741. 4 is offered as 3's square (the square is only calculated for the preceeding
  742. number). This is caused by the parameters being placed on the function's 
  743. stack (temporary storage), where the function expects to find them.
  744. Unfortunately the storage of these values occurs in reverse order, i.e. first
  745. i*i++ is stored and i is incremented. Then the first parameter of i which 
  746. already has the wrong value appears.
  747.  
  748. C language offers many routes to writing short and efficient programs. However
  749. there is the danger of the new programmer trying too much, too soon. The side
  750. effects shouldn't occur in functions or macros unless you know their effects 
  751. on all variables and parameters. Again, make use of the precedence table as
  752. needed (see appendices for this table.)
  753.  
  754.                 PAGE 197
  755.  
  756. -----------------------------------------------------------------------------
  757.  
  758. 22.2 LIBRARY MACROS.
  759.  
  760. Frequently used macros are best stored in a library, from which they can 
  761. easily be inserted in source code with #include. This group includes various
  762. conversion functions for letters (e.g. testing is a letter is upper or lower
  763. case). The following defines have the following tasks:
  764.  
  765. Convert uppercase letters to lowercase letters :
  766.  
  767.     #define to_lower(c) ((c)+32)
  768.  
  769. Convert lowercase to uppercase letters :
  770.     
  771.     #define to_upper(c) ((c)-32)
  772.  
  773. Test for letters (1=yes,0=no):
  774.  
  775.     #define isalpha(c) ((c)>='A' && (c)<='Z' || (c)>='a' && (c)<='z')
  776.  
  777. Test for uppercase letters (1=yes / 0 = no)
  778.  
  779.     #define isupper(c) ((c)>='A' && (c)<='Z')
  780.  
  781. Test for lowercase letters 
  782.     
  783.     #define islower(c) ((c)>='a' && (c)<='z')
  784.  
  785. Test for number (yes = 1, no = 0)
  786.  
  787.     #define isdigit(c) ((c)>='0' && (c)<='9')
  788.  
  789. Test for alphanumberic characters.
  790.  
  791.     #define isalnum(c) (isalpha(c) || isdigit(c))
  792.  
  793. Test for blank,tab,linefeed,carriage return or formfeed.
  794.  
  795.     #define isspace(c) ((c)=='' || (c)=='\t' || (c)=='\r' ||
  796.      (c)=='\n' || (c)=='\f')
  797.  
  798. Test for special characters.
  799.  
  800.     #define ispunct(c) ((c)>=' ' &&!isalnum(c))
  801.  
  802. Test for printable characters.
  803.  
  804.     #define isprint(c) ((c)>=040 && (c)<=0176)
  805.  
  806.                 PAGE 198
  807.  
  808. ---------------------------------------------------------------------------
  809.  
  810. Test for control characters.
  811.  
  812.     #define iscntrl(c)  ((c)>= 0 && ((c)==0177 || (c)<' '))
  813.  
  814. Test for ASCII characters.
  815.  
  816.     #definfe isascii(c)  ((c)>=0 && (c)<=200)
  817.  
  818. These defines should be easily understood once they are examined. They should
  819. be written into a file name CTYPE.H, unless this type of file is already
  820. available in a subdirectory. If the following line occurs in a program you 
  821. know what should be found there:
  822.  
  823.     #include<ctype.h>
  824.  
  825. Remember that for the test for letters, only the 26 letters of the alphabet 
  826. are considered. International special characters are not viewed as letters.
  827. Maybe, they can be implemented in a suitable manner. Perhaps the STRCMP
  828. can be converted with the new defines.
  829.  
  830.     char *s, *t;
  831.     int n, compare;
  832.     
  833.     compare = strcmp(s,t);
  834.     compare = strncmp(s, t, n);
  835.     compare = stricmp(s,t);
  836.     compare = strnicmp(s, t, n);
  837.  
  838. The first function is identical to the routine you programmed. If compares
  839. two strings and returns the result of the comparisons. In the second function
  840. STRNCMP, the third value indicates up to what point the comparison should be
  841. made. The comparison can be limited this way up to n characters. For example
  842. only the first four elements. The functions which have an i in the name 
  843. dont differentiate between upper and lower case letters. Comparing the two 
  844. strings "aBcDeF" and "ABcdeF" with the function returns zero because both 
  845. strings are equal.
  846.  
  847.                 PAGE 199
  848.  
  849. ----------------------------------------------------------------------------
  850.  
  851.             CHAPTER 23 - COMMUNICATION.
  852.  
  853. The programs written so far have only displayed data on the screen or 
  854. requested keyboard input. It's time to communicate with other devices. The
  855. CLI is the easiest way to transfer data. In this chapter we'll communicate
  856. with the CLI as well as other devices.
  857.  
  858. 23.1 PASSING DATA WITH THE CLI.
  859.  
  860. All programs are called from the CLI by entering the filename and arguments 
  861. (if needed). Here is one type of call to invoke ED:
  862.  
  863.     ED file.c SIZE 50000
  864.  
  865. This complete line can be made available to the called program, though not in 
  866. this form. The operating system modifies this line slightly.
  867.  
  868. Now comes the question of data transfer. The main function containing two 
  869. arguments controls this. Until now every call appeared as follows :
  870.  
  871.     main()
  872.     {
  873.      . . .
  874.       . . . 
  875.     }
  876.  
  877. THe next code passed two values from the calling program from either the CLI
  878. or a MAKE file. The first value represents the amount of information amd a 
  879. pointer to a CHAR pointer. This sounds somewhat complicated, but looking at 
  880. the input line of the program should make it clear. First the new version of
  881. MAIN two arguments:
  882.  
  883.     main(argc,argv)
  884.     int argc;
  885.     char *argv[];
  886.     {
  887.      . . . 
  888.      . . . 
  889.     }
  890.  
  891. The name of our fictional program is PRG. Look at this sample entry:
  892.  
  893.     prt Text1 parameter 3 -pi
  894.  
  895.                 PAGE 203
  896.  
  897. -----------------------------------------------------------------------------
  898.  
  899. After the program call, the variable ARGC contains the number of arguments
  900. (5). Why is 5 passed when only 4 arguments are available? The fifth argument
  901. comes from adding the program name used during the call. The name ARCG
  902. (ARGument Count) is a random choice since it is an auto variable of the 
  903. MAIN function. The name ARGV (ARGument Vector) handles vectors.
  904.  
  905. Spaces or tabs separate every argument of the input line. After the call the
  906. pointers of *argv[] point to :
  907.  
  908.     argv[0] "prg"
  909.     argv[1] "Text1"
  910.     argv[2] "Parameter"
  911.     argv[3] "3"
  912.     argv[4] "-pi"
  913.  
  914. Let's examine the data. Use the following program to print the data:
  915.  
  916.     /* arg_test.c  23.1 */
  917.     main(argc,argv)
  918.     int argc;
  919.     char *argv[];
  920.     {
  921.       while(--argc >= 0)
  922.         puts(*argv++);
  923.  
  924. What can be done with this?. You can access a small math program by entering
  925. the following in CLI:
  926.  
  927.     compute 123.5 * 4711
  928.  
  929. The following program is written so that it will only perform simple 
  930. calculations consisting of two numbers and an operator. Feel free to improve
  931. on the program as needed:
  932.  
  933.     /* arg_math.c  23.1 */
  934.     extern double atof();     /* Declaration */
  935.     
  936.     int error = 0;
  937.  
  938.     main(argc,argv)
  939.     int argc;
  940.     char *argv[];
  941.     {
  942.        double result, value();
  943.  
  944.        if(argc !=4)
  945.         printf("\nWrong Entry\nCall: Number1 # Number2\n");
  946.        else
  947.         {
  948.            result = value(argv[1], argv[2], argv[3]);
  949.            if(!error)
  950.              printf("\n%s %s %s = %.91f\n", argv[1], argv[2],
  951.                              argv[3], result);
  952.         }
  953.     }
  954.  
  955.                 PAGE 204
  956.  
  957. ---------------------------------------------------------------------------
  958.  
  959.     double value(number1,op,number2)
  960.     char *number1, *op, *number2;
  961.     {
  962.        double z1 = atof(number1);
  963.        double z2 = atof(number2);
  964.  
  965.        switch(*op)   /* Only the first character */
  966.           {
  967.         case '/':
  968.           return(z1 / z2);
  969.         case '*':
  970.           return(z1 * z2);
  971.         case '+':
  972.           return(z1 + z2);
  973.         case '-':
  974.           return(z1 - z2);
  975.         default:
  976.           printf("\nUnknown Operator >%s<\n",7,op);
  977.           error = 1;
  978.           return(0.00)
  979.         }
  980.      }
  981.  
  982. LATTICE :
  983.  
  984. The mathematical function/floating point library must be linked to the 
  985. standard library because it contains the atof function. Example:
  986.  
  987.     lc -Lm math2
  988.  
  989. AZTEC :
  990.  
  991. If you work with Aztec C, the mathematical function/floating point library
  992. must be linked to the standard library C.LIB since it contains the ATOF
  993. function. Example:
  994.  
  995.     cc +L math2.c
  996.     ln math2.o -lm -lc
  997.  
  998.                 PAGE 205
  999.  
  1000. -----------------------------------------------------------------------------
  1001.  
  1002. 23.2 BUFFERED INPUT / OUTPUT.
  1003.  
  1004. Many programs require permanent data storage for files, whether it is a 
  1005. database or a word processor. These require routines that control input /
  1006. output with external devices such as printers, disk drives, RS-232 interfaces
  1007. or a hard disk drive. The operating system provides various functions for this
  1008. purpose. These routines can be divided into 2 groups; buffered input/output
  1009. and unbuffered input/output.
  1010.  
  1011. This type of data transfer does a lot of work, even though it may not seem 
  1012. evident at first. For example, all data selected for transfer to disk goes to 
  1013. a buffer first. When this buffer completely fills, the data goes to the disk.
  1014. The question is, why do it this way?
  1015.  
  1016. A disk drives reads and writes information much slower than the computer can 
  1017. send or receive it. This is caused by the mechanics of the disk drive. Before
  1018. writing any data, the read/write head must move to the track where the data is
  1019. stored. Then it must wait until the disk rotates to the right location. Only 
  1020. then can the data be written. Although this timing is brief in human terms,
  1021. the computer (actually its CPU) is kept waiting a very long time.
  1022.  
  1023. DISK BUFFERS:
  1024.  
  1025. If you transmitted every character with this method, the computer would spend
  1026. more time waiting to place a single character on the disk drive than 
  1027. performing any other task. For this reason, smaller amounts of data move to an
  1028. area of memory in the computer before transmission. Once this buffer fills,
  1029. the data moves to the disk drive. This reduces computer waiting time. As soon 
  1030. as the drive writes the first character to the proper place, it can place the
  1031. other data right behind it and place the complete buffer in one pass. This
  1032. reduces the number of disk accesses, which accelerates program execution.
  1033. The same principle is also used for reading data.
  1034.  
  1035. The functions which perform this job are GETC and PUTC, which like their 
  1036. relatives GETCHAR and PUTCHAR, input or output a character.
  1037.  
  1038. These functions are not part of the C language. For this reason they can be 
  1039. found in a library, or in this case as a #define in the Header file (.h).
  1040. The definition of GETC and PUTC can also be found in the STDIO.H file with the
  1041. familiar PUTCHAR and GETCHAR.
  1042.  
  1043.     #define getc(p) (--(p)->_rcnt>=0? *(p)->ptr++:_filbp(p))
  1044.     #define getchar() getc(stdin)
  1045.     #define putc(p) (--(p)->_wcnt>=0? *(p)->_prt++:_flsbf((c),p))
  1046.     #define putchar() putc(c,stdout)
  1047.  
  1048.                 PAGE 206
  1049.  
  1050. ----------------------------------------------------------------------------
  1051.  
  1052.  
  1053. Lets clear some of this up. The definitions of PUTCHAR and GETCHAR are all 
  1054. you need to know for now. Both can be traced back to GETC and PUTC and
  1055. represent special versions of the two functions.
  1056.  
  1057. Before the first character can be moved with these functions, a channel must
  1058. be opened. A channel is just a data line to a certain device. No cables 
  1059. actually open up a channel, but the system knows where to send the 
  1060. information. A special code obtained from the operating system during the 
  1061. opening of the channel allows addressing the device at any time. Devices and
  1062. individual disk files can be addressed.
  1063.  
  1064. Several files can be accessed on the same drive without having data conflict.
  1065. The file pointer indicates the channel. Since a buffer is used for input / 
  1066. output, the computer must be informed of where the data should be stored 
  1067. intermittently and how large a space must be reserved. A structure named
  1068. FILE (notice the uppercase letters) defined in STDIO.H contains all necessary
  1069. data for buffered input / output. The following listing writes a file and
  1070. then reads it again:
  1071.  
  1072.     /* fprint-fscan.c 23.2.1 */
  1073.     #include <stdio.h>
  1074.  
  1075.     main()
  1076.     {
  1077.        FILE *input, *output, *fopen();
  1078.        char filename[81], text[200];
  1079.     
  1080.        printf("Please input file name!\n");
  1081.        scanf("%80s",filename);
  1082.        printf("Input a (long) word!\n");
  1083.        scanf("%200s",text);
  1084.  
  1085.        output = fopen(filename,"w");
  1086.        printf("Filehandle %d\n", output);
  1087.        fprintf(output,"%s",text);
  1088.        fclose(output);
  1089.  
  1090.        input = fopen(filename,"r");
  1091.        printf("Filehandle %d\n", input);
  1092.        fscanf(input,"%200s",text);
  1093.        fclose(input);
  1094.        printf("The Text: >%s<\n",text);
  1095.     }
  1096.  
  1097. THE FOPEN FUNCTION :
  1098.  
  1099. The FOPEN function opens the channel and returns the file pointer, used for
  1100. all future access to this file. Since FOPEN returns something other than an 
  1101. integer, it must be declared as a function which returns a file pointer.
  1102. This routine requires two arguments; the name of the file and the access mode.
  1103. The user can enter the name. The access mode tells the computer what should 
  1104. be done with the file. The mode can be one of three letters :
  1105.  
  1106.                 PAGE 207
  1107.  
  1108. ----------------------------------------------------------------------------
  1109.  
  1110.     r - opens a file for reading.
  1111.     w - opens a file for writing.
  1112.     a - opens a file for adding additional data.
  1113.  
  1114. A file opened for reading (r) can only read data not write data. A file 
  1115. opened for writing lets you write data. The append mode writes data to the end
  1116. of an existing file. In normal write (w) mode, writing starts at the beginning
  1117. of the file and overwrites existing data. This can easily lead to loss of 
  1118. data. The example above overwrites and existing file and destroys some 
  1119. previouslt stored data.
  1120.  
  1121. After the opening the file is ready for writing. The file handle appears on 
  1122. the screen. The SCANF function assigns the characters entered throught the
  1123. keyboard to the string TEXT. The FPRINTF function can write data to a file. It
  1124. is almost identical to the printf routine, but differs in the first argument.
  1125. Before the command string, a file handle must be passed to assign the 
  1126. information to the correct file. After writing, the file closes. This step is
  1127. very important because of the buffer. All input/output goes there for 
  1128. intermediate storage until the buffer is filled. Some of the data input can
  1129. still be stored in that buffer. If the user assumes that everything was stored
  1130. on the disk and switches off the computer, the data still in the buffer would
  1131. be lost. For this reason the FCLOSE call closes the channel after writing the
  1132. remaining buffer contents to the open file.
  1133.  
  1134. Now the file re-opens again, but this time for reading which is signated with
  1135. the mode 'r'. Since keyboard input always uses SCANF, the FSCANF is used here.
  1136. First the file pointer and the arguments of the scanf routine must be passed 
  1137. to the read function.
  1138.  
  1139. The correct closing of the file follows. If you ommitted this instruction data
  1140. loss cannot result. However, it's good practise to close and opened file 
  1141. immediately after use, not only because it's good housekeeping, but also 
  1142. because a computer can maintain only a certain number of open files. If more 
  1143. files are opened, a channel cannot remain open at a certain time. Should an
  1144. error occur, because the operating system cannot make a channel available,
  1145. the file pointer is returned as zero. This happens when no channels are 
  1146. available or the file which should be read does not exist.
  1147.  
  1148. The next example program is a small copy program. It is called with arguments 
  1149. and is therefore able to accept arguments from main.
  1150. One difficulty must be avoided. Nobody knows in advance what type of data will
  1151. be transmitted. The fscanf cannot be used since it has to indicate if strings
  1152. or numbers are used. The program can only read one character at a time. The 
  1153. scanf function with the format instruction %c can be used, but the FGETC 
  1154. function works much better. It reads a character from an input file and is
  1155. much faster than the FSCANF function. The FPUTC statements performs the 
  1156. output.
  1157.  
  1158.                 PAGE 208
  1159.  
  1160. ------------------------------------------------------------------------------
  1161.  
  1162. After opening the two files, a character is read and displayed immediately ,
  1163. until ...... You dont know when all the data has been copied How can you 
  1164. detect when the last character has been read?. The problem has already been
  1165. solved. FGETC returns a special character if no additional information is 
  1166. available - end of file (EOF). The #include file STDIO.H contains this text 
  1167. as a #define so that the incoming characters only have to be compared with
  1168. EOF.
  1169.  
  1170. EOF is stored there as -1. This has consequences which at first are not 
  1171. evident. Valid data have codes which in FGETC are between 0 and 255. Wnen -1
  1172. appears, no CHAR variable can be selected to accept the character. Either 
  1173. negative numbers are ignored or data is lost. For this reason, int variables 
  1174. are used even if only a CHAR element is stored in them.
  1175.  
  1176.     /* Copier.c 23.2.1.     */
  1177.     #include <stdio.h>
  1178.     
  1179.     main(argc,argv)
  1180.     int argc;
  1181.     char *argv[];
  1182.     {
  1183.         long copy();  /* If it is interesting.     */
  1184.  
  1185.         if( argc != 3)
  1186.            {
  1187.         printf("Bad Arguments!\n");
  1188.           printf("From_file to_file\n");
  1189.            }
  1190.         else
  1191.         copy(argv[1],argv[2]);
  1192.     }
  1193.  
  1194.     copy(fromfile,tofile)
  1195.     char *fromfile, *tofile;
  1196.     {
  1197.        FILE *input, *output, *fopen();
  1198.        register long counter = 0;
  1199.        register int c;
  1200.  
  1201.        if(!(input = fopen(fromfile,"rb")))
  1202.         /* Open a binary file */
  1203.          {
  1204.         printf("%s cannot be opened!\n",fromfile);
  1205.          }
  1206.        
  1207.        if(!(output = fopen(tofile,"wb")))
  1208.          {
  1209.         printf("%s cannot be opened!\n",tofile);
  1210.         fclose(input); /* Was OK */
  1211.         return 0 ; /* zero */
  1212.           }
  1213.  
  1214.         while((c=fgetc(input))!=EOF)
  1215.           {
  1216.           fputc(c,output);
  1217.         counter ++;
  1218.           }
  1219.  
  1220.        fclose(input);
  1221.        fclose(output);
  1222.        printf("\n%ldBytes copied!\n",counter);
  1223.        return(counter);
  1224.     }
  1225.  
  1226.                 PAGE 209
  1227.  
  1228. -----------------------------------------------------------------------------
  1229.  
  1230. The copy program is called as follows:
  1231.  
  1232. copier [d:] [\path]name1 [.ext] [d:][\path] name2 [.ext]
  1233.  
  1234. Everything written into the brackets is optional and can be omitted. Only two
  1235. filenames must be provided. If an error should occur during the opening of 
  1236. the two files, an error message appears. An error message is also displayed if
  1237. too many or too few arguments are passed.
  1238.  
  1239. Since it is very slow, the program is unsuitable for everyday use. However, 
  1240. it's a suitable demonstration program. Let's limit the discussion to the 
  1241. essentials. The files are opened as binary files with WB and RB (Aztec 
  1242. compiler users should omit the B; the file always opens as a binary file).
  1243. For example, this prevents any conversions being attempted which could occur
  1244. in text files. During reading all \r characters (carriage return) are erased
  1245. automatically and characters with code 26 (<Ctrl><z>) are converted to EOF.
  1246. During write the linefeed (\n) is converted to a character combination 
  1247. (\r\n). Opening the file with the appendix b (binary) returns all characters 
  1248. as they are stored in the file and not converted.
  1249.  
  1250.                 PAGE 210
  1251.  
  1252. -----------------------------------------------------------------------------
  1253.  
  1254. 23.3 MORE BUFFERED INPUT / OUTPUT.
  1255.  
  1256. Besides FGETC,FPUTC,FSCANF and FPRINTF there are some other important
  1257. functions that use the internal buffer. Among them are FREAD and FWRITE.
  1258. These routines transport any number of bytes. For this reason two additional 
  1259. arguments are required for FREAD and FWRITE. One argument is the area which 
  1260. serves as the bufferand the other the size of the units to be transmitted.
  1261. This needs some explanation. The buffer in previously used functions was 
  1262. always located in the FILE structure. Since only small amounts of data were
  1263. transported, the buffer did not have to be too large (512 bytes). Since the 
  1264. user can now determine how much data is transmitted, the buffer may be too
  1265. small. For this reason the use must define the memory area, thereby setting 
  1266. the maximum size of the data transfer. The data size must also be indicated.
  1267. In GETC and PUTC only 2 character can be transmitted (1 byte) and the size of 
  1268. the CHAR object doesnt have to be indicated. If a long value, instead of a 
  1269. character, is stored, 40 bytes must be transmitted for 10 of these values.
  1270. The object size (in this case 4 bytes each) is the second argument that 
  1271. must be passed. If the data type is unknown, the SIZEOF operator should be 
  1272. used because it returns the correct value.
  1273.  
  1274. Besides these two arguments the number of units to be transmitted (char,int
  1275.  structure ...) and the file pointer must be transmitted. The buffer size 
  1276. determined at the time of definition should not be too small. A call of this
  1277. function appears as follows :
  1278.  
  1279.     Datatype  buffer[element]; /* Definition of the buffer */
  1280.     
  1281.     fread(buffer,sizeof(Datatype), Element, file_ptr);
  1282.  
  1283. The first argument is the buffer from which the data is read. The buffer
  1284. should be the same type as the units to be transmitted. The second value is 
  1285. the unit size. This unit is a data package which can be transmitted as one
  1286. item. If long variables are transmitted it makes sense to indicate 4 bytes 
  1287. as the data block length, since 4 byte units are the normal requirement.
  1288. If 100 double variables are stored, 100 is placed at the element. Finally, 
  1289. a file pointer is added, which was received from FOPEN.
  1290.  
  1291. If data is read or written, the argument sequence and type remains the same.
  1292. The FWRITE function stores the data using this syntax :
  1293.  
  1294.     int table[876], size = 876;
  1295.     FILE *output_ptr;
  1296.  
  1297.     fwrite(table,sizeof(double),size,output_ptr);
  1298.  
  1299.                 PAGE 211
  1300.  
  1301. -----------------------------------------------------------------------------
  1302.  
  1303. If the value of size is not specified, either through a variable or with a 
  1304. #define, the SIZEOF operator can be read:
  1305.  
  1306.     sizeof(table)/sizeof(int)
  1307.  
  1308. The function returns the numbers of complete transmitted data packages. This
  1309. ensures storage of all data. During copying, data can be read until the 
  1310. number of requested data differs from the data delivered. If FREAD returns 
  1311. a zero, the last data was read. A sample program:
  1312.  
  1313.     /* fread.c 23.3.3. */
  1314.     #include <stiod.h>
  1315.     
  1316.     #define NUM_DATA (sizeof(data)/sizeof(long))
  1317.  
  1318.     Long data[] = 
  1319.     {
  1320.       4711, 815, 1024, 1, 31415926, 0, -13 ,10,
  1321.       0xFFFF, 065432
  1322.     };
  1323.  
  1324.     main()
  1325.     {
  1326.       FILE *input, *output, *fopen();
  1327.       int i;
  1328.       long test[NUM_DATA];
  1329.       char filename[81];
  1330.  
  1331.       printf("Please input filename ! \n");
  1332.       scanf("%80s", filename);
  1333.       printf("Data size %d, Elements %d\n",sizeof(data), NUM_DATA);
  1334.       output = fopen(filename,"wb"); /* Binary ! */
  1335.       fwrite(data,sizeof(long),NUM_DATA,output);
  1336.       fclose(output);
  1337.  
  1338.       printf("Read data!\n");
  1339.       input = fopen(filename,"rb");
  1340.       printf("%d Elements Read\n",fread(test,sizeof(long),
  1341.                      NUM_DATA,input));
  1342.       fclose(input);
  1343.       for(i=0; i < NUM_DATA,i++)
  1344.         printf("%ld\t",text[i]);
  1345.       printf("Done!\n");
  1346.     }
  1347.  
  1348. This program writes a long array to the file after entering the filename. The
  1349. array size and the number of elements appear on the screen. The define 
  1350. NUM_DATA stores all data on the disk. After closing the file, another array
  1351. accepts the data read. All data appears on the monitor.
  1352.  
  1353. Lattice C users must open the file as binary, or internal conversion produces
  1354. false values in the variables. If FWRITE and FREAD are used, the file must
  1355. also be opened as a binary file.
  1356.  
  1357.                 PAGE 212
  1358.  
  1359. -----------------------------------------------------------------------------
  1360.  
  1361. 23.4 UNBUFFERED INPUT / OUTPUT.
  1362.  
  1363. Besides the buffered functions just demonstrated, there are other routines 
  1364. which do not require a buffer. The data to be transmitted don't have to be 
  1365. stored in a buffer, but can be stored immediately. This cancels all the 
  1366. effort required for the buffer and internal pointers. This also cancels the 
  1367. need for a file pointer through which the operating system can access the 
  1368. buffer. A channel number assigned during the opening must be used as
  1369. identification. This channel number is stored in an integer variale and
  1370. replaces the file pointer in all calls. The OPEN function opens a file. 
  1371. Filename and filemode (as an integer) arguments pass to the function. In
  1372. FOPEN the mode must be a string, while in OPEN the mode is one of three
  1373. values: 0,1,2 or 8. These numbers correspond to the strings r,w and a.
  1374.  
  1375.     0 - Opens a file for reading.
  1376.     1 - Opens a file for writing.
  1377.     2 - Opens a file for reading and writing.
  1378.     8 - Opens a file for appending.
  1379.  
  1380. Instead of these numbers DEFINES can be used to make the program more 
  1381. readable. They are stored in a header file name FCNTL.H and are defined as
  1382. follows :
  1383.  
  1384.     #DEFINE O_RDONLY 0
  1385.     #DEFINE 0_WRONLY 1
  1386.     #DEFINE 0_RDWR 2
  1387.     #DEFINE 0_APPEND 8
  1388.  
  1389. To use these defines, the file must be included in the source with the 
  1390. sequence:
  1391.  
  1392.     #include <fcntl.h>
  1393.  
  1394. Another difference from the FOPEN routine is that OPEN always assumes the 
  1395. existence of a file. The following call creates a file even if the file 
  1396. already exists :
  1397.  
  1398.     fopen("filename","w");
  1399.  
  1400. The OPEN function always prompts for the name of an existing file. The CREATE
  1401. function must be used to create a new file.
  1402.  
  1403. The CREATE function returns an integer (the file handle). You dont need to 
  1404. call OPEN. If an error occurs and the file cannot be opened, both CREATE and
  1405. OPEN return the value -1. Before using the returned value as a file handle,
  1406. check the file handle for a value of -1, or the system will crash.
  1407.  
  1408.  
  1409.                 PAGE 213
  1410.  
  1411. -----------------------------------------------------------------------------
  1412.  
  1413. The key combination of <Ctrl><Commodore><Amiga> resets the computer but 
  1414. deletes any data in the RAM disk.
  1415.  
  1416. A file opened in this manner allows writing using the WRITE function instead 
  1417. of the FWRITE function. Since this method uses no buffer, only certain 
  1418. input/output functions can be accessed. Also, the READ function replaces the 
  1419. FREAD function. Buffered functions have an F in front of their name (e.g. 
  1420. fopen, fread, fwrite etc..). Unbuffered functions omit the F. The CLOSE
  1421. function closes an unbuffered file.
  1422.  
  1423. The following function stores a list of DOUBLE numbers :
  1424.  
  1425.     /* write-read.c  23.4 */
  1426.     #define NUMBER (sizeof(data)/sizeof(double))
  1427.  
  1428.     double data[] = 
  1429.     { 
  1430.       1.5, 2.0, 3,14159265, 2.718281828,
  1431.     };
  1432.  
  1433.     main()
  1434.     {
  1435.       int handle, dummy = 0, i, actual;
  1436.       double data2[NUMBER];
  1437.       char filename[81];
  1438.  
  1439.       printf("Please input filename :\n");
  1440.       scanf("%80s",filename);
  1441.  
  1442.       handle = create(filename,dummy); /* Create new *./
  1443.       if(handle != -1) /* mEverything OK */
  1444.         {
  1445.         actual = write(handle,data,sizeof(data));
  1446.             printf("Desired %d Bytes, Actual %D bytes\n",
  1447.             sizeof(data),actual);
  1448.             close(handle);
  1449.         }
  1450.       else
  1451.         printf("Error during Creation of %s\n",filename);
  1452.  
  1453.       handle = open(filename,0,dummy); /* Read */
  1454.       if(handle != -1) /* Everything ok */
  1455.         {
  1456.         actual = read(handle, data2, sizeof(data));
  1457.             printf("Desired %d Bytes, Actual %d Bytes\n",
  1458.             sizeof(data), actual);
  1459.             close(handle);
  1460.         }
  1461.  
  1462.       else
  1463.         printf("Error during opening of %s\n",filename);
  1464.  
  1465.       for(i=0,i < NUMBER,i++)
  1466.         printf("%.81f  ",data2[i]);
  1467.       printf("Thats all ! \n");
  1468.     }
  1469.  
  1470.                 PAGE 214
  1471.  
  1472. -----------------------------------------------------------------------------
  1473.  
  1474. The OPEN and CREATE functions, which return a file handle, have a peculiar 
  1475. variable named DUMMY. This variable respresents a value which may be 
  1476. unneccessary, but the compiler checks for the variable if needed. The value
  1477. stored in dummy, as the name suggests, has no significance. In OPEN the 
  1478. second argument represents the DUMMY value for reading or writing.
  1479.  
  1480. The WRITE and READ functions have one less argument than FWRITE and FREAD.
  1481. Furthermore (and this is important), the file handle is placed at the 
  1482. beginning, not at the end as in buffered functions. The unbuffered functions
  1483. transfer data one byte at a time only. This means that the size indication
  1484. is unnecessary. The return value is the number of bytes transmitted so far.
  1485.  
  1486.                 PAGE 215
  1487.  
  1488. ----------------------------------------------------------------------------
  1489.  
  1490. 23.5 DIRECT ACCESS.
  1491.  
  1492. The following functions provided the user with the ability to directly access
  1493. certain characters in a file. The difference from the usual read lies in the 
  1494. fact that not every character must be read starting at the beginning of the
  1495. file until the program finds the particular characters. To access the last 
  1496. 10 characters in a file of 1000 characters, 990 characters would have to 
  1497. be read first. With direct access, the command starts the reading after the
  1498. 990th character. A file pointer always points to the last accessed data. 
  1499. During a sequential read or write, when one character after another is 
  1500. processed, this pointer always increments by one. The functions LSEEK and
  1501. FSEEK let the user set this pointer to any desired position. Both routines
  1502. require 3 arguments for this, where LSEEK is the unbuffered version and FSEEK
  1503. is the buffered version. For this reason LSEEK requires the file handle as 
  1504. the first arguments, while FSEEK requires a file pointer. A second value 
  1505. follows, the number of bytes by which the pointer must be moved. Positive 
  1506. values move the pointer toward then end of the file, negative values toward 
  1507. the beginning of the file. This value must be passed as a LONG value.
  1508. The third argument, an integer, indicates from which position the movement 
  1509. should start. A 0 sets the data pointer to the beginning of the file, 2 to 
  1510. the end of the file and 1 to the current position. Some examples :
  1511.  
  1512.     lseek(f_handle,100L,0);
  1513.  
  1514. The data pointer moves to position 100 (i.e. 100 characters from the start 
  1515. of the file). If now points to the 101st byte of the file. The following
  1516. function places the pointer at position 70, since the call passed the value
  1517. 1:
  1518.  
  1519.     lseek(f_handle, 70L,1);
  1520.  
  1521. The 1 indicates the calculation of the new pointer position from the current
  1522. location. To move the pointer 20 characters toward the beginning of the file,
  1523. the following function is required:
  1524.  
  1525.     lseek(f_handle, -20L,1);
  1526.  
  1527. If the processing of a file should start from the end of the file, the pointer
  1528. can be set to the last position of the file with :
  1529.  
  1530.     lseek(f_handle, 0L,2);
  1531.  
  1532. This shows that in mode 2 (end of the file), only negative numbers or zero 
  1533. are permitted since the pointer is already at the end of the file. In mode
  1534. 0 only positive numbers or zero can be used. These functions only move the
  1535. file pointer.
  1536.  
  1537.                 PAGE 216
  1538.  
  1539. -----------------------------------------------------------------------------
  1540.  
  1541. The data must be read or written with the various functions such as READ or
  1542. WRITE.
  1543.  
  1544. The LSEEK function returns the value of the data pointer after the move. FSEEK
  1545. returns either 0 or -1. With a -1 an error occured, otherwise everything 
  1546. proceeded without a problem.
  1547.  
  1548. Two additional routines, a buffered and an unbuffered version can sense the 
  1549. current value of the data pointer. Since it is a long value the FTELL and 
  1550. TELL functions must be declared first. The only required argument of both
  1551. functions is the proper file handle.
  1552.  
  1553. The function call could be replaced with the call :
  1554.  
  1555.     lseek(f_handle,0L,1);
  1556.  
  1557. which indicates the value of the current data pointer.
  1558.  
  1559.                 PAGE 217
  1560.  
  1561. -----------------------------------------------------------------------------
  1562.  
  1563. 23.6 READING A CHARACTER.
  1564.  
  1565. Our previous programs used SCANF to read a character from the keyboard. The
  1566. problem with this is that you have to press the <Return> key after every
  1567. character. A word processing program would be intolerable under these 
  1568. conditions. Even a modest application such as controlling the cursor in all
  1569. four directions would be difficult.
  1570.  
  1571. THE GETCHAR FUNCTION.
  1572.  
  1573. The GETCHAR function offers help. This function receives the pressed key's 
  1574. code immediately. Even here there is a difference between theory and practise.
  1575. Almost all other C implementations use this function according to the rules.
  1576. Excpet for the AMIGA. The amiga requires the <Return> key for execution.
  1577.  
  1578.  
  1579. 23.6.1. STANDARD INPUT / OUTPUT.
  1580.  
  1581. Usually data is entered through the keyoboard into the computer. Messages and
  1582. the results of calculations usually appear on the screen. These two devices 
  1583. combined are called the console. If you do not instruct the computer to get
  1584. the source data from or send the destination to a particular device, it 
  1585. defaults to the standard input/output (keyboard and screen). The good news
  1586. is that these devices can be changed by the user. The Amiga can input data 
  1587. from another device instead of the keyboard.
  1588.  
  1589. STANDARD DEVICES.
  1590.  
  1591. The standard input device is the keyboard. The standard output device is the 
  1592. monitor screen or screen for short. In various windows the output defaults to
  1593. the CLI window. This window is the standard output for your previous programs.
  1594. All CLI limitations also apply to your program. This causes the error in 
  1595. GETCHAR.
  1596.  
  1597. The CLI is line-orientated. Data processes after you enter your input and 
  1598. press the <Return> key. Anything can be typed in without the computer 
  1599. reporting, during input, that this isn't permitted. Press <Ctrl><G> to make
  1600. the screen blink. Even though these characters can be entered you cannot 
  1601. display them on the screen. If you try this the blinking function executes.
  1602. The CLI is an input console which processes whole lines and not single keys.
  1603.  
  1604. The rule of only using single keys also applies to programs started from the
  1605. CLI. Now that you know why <Return> must be pressed, it's time to create a 
  1606. user defined window to solve this problem.
  1607.  
  1608.                 PAGE 218
  1609.  
  1610. -----------------------------------------------------------------------------
  1611.  
  1612. 23.7 A USER WINDOW.
  1613.  
  1614. Creating a personal window is fairly simple. Developing your own window 
  1615. consists of opening an output file, since the output is written into this 
  1616. newly created window. The keyboard then acts as the input device according to 
  1617. the arguments set by the user window.
  1618.  
  1619. 23.7.1 THE THREE WINDOWS.
  1620.  
  1621. You have three device options for opening non-CLI windows :
  1622.  
  1623.     *
  1624.     CON:
  1625.     RAW:
  1626.  
  1627. These strings follow the OPEN command in the CLI. They replace the usual 
  1628. filenames and drive specifiers. The asterisk sends data directly to the 
  1629. CLI window; a new window isn't created. Nothing has changed for the input 
  1630. either. Opening an asterisk device only causes the same trouble as before.
  1631.  
  1632. The CON: device creates a user window. The OPEN call as listed below creates
  1633. an unbuffered OPEN filename and a pathname of CON:
  1634.  
  1635.     open("CON:0/0/200/50/title line",0,dummy);
  1636.  
  1637. The CON: device name replaces the drive specifier and the new windows's 
  1638. co-ordinates follow. Finally the name TITLE LINE appears in the upper left
  1639. corner of the title bar. A slash character (/) separates the window arguments.
  1640. The other arguments such a 0 (read) and the dummy value follow the usual 
  1641. syntax of the OPEN routine.
  1642.  
  1643. The returned file handle appears in the examples with all READ calls. An 
  1644. 81-character string acts as a buffer. Try this short routine :
  1645.  
  1646.     /* window1.c 23.7.1 */
  1647.     #define c *character
  1648.     #define ESC 27
  1649.  
  1650.     main()
  1651.     {
  1652.        int dummy = 0, num, handle;
  1653.        char character[81], line[256];
  1654.        handle = open("CON:0/0/200/50/My Program",0,dummy);
  1655.        printf("Opens %d Handle\n",handle);
  1656.        if (handle!=-1)
  1657.         {
  1658.            do
  1659.         {
  1660.            num = read(handle,character,1);
  1661.            printf("Character code >%c< Code %d\n",c,c);
  1662.         }while (c!=ESC);
  1663.          close(handle);
  1664.        }
  1665.     }
  1666.  
  1667.                 PAGE 220
  1668.  
  1669. ----------------------------------------------------------------------------
  1670.  
  1671. If you forget to test for the successful opening of a file, the computer may
  1672. crash using -1 as handle values. When the program executes a new window 
  1673. appears; nothing happens after you press a key. All keys are processed only
  1674. after you press the <Return> key. A new window appears. Unfortunately the 
  1675. window only works in line mode, like the normal CLI window. Press 
  1676. <Esc><Return> to exit the program.
  1677.  
  1678. The RAW: option also creates a window. The difference between this option and
  1679. CON: is the way the information is displayed. A RAW: window displays 
  1680. information in unfiltered form (i.e. control characters and garbage appear).
  1681. Change CON: to RAW: in the above program. Compile ,link and run this new 
  1682. version and watch what happens next.
  1683.  
  1684. Again, a new user window appears. You can size this window and move it around 
  1685. the screen. Select the new window and sent data to it (type on the keyboard).
  1686. Notice that the window reacts to every keypress. However, the input doesnt
  1687. appear in the user window. The program seems to be ignoring the RAW: 
  1688. specification.
  1689.  
  1690. All output with printf continues to go to the CLI window. This isn't 
  1691. surprising since it's the standard output device for programs started from
  1692. the CLI. To write something into the user window, for which a special handle
  1693. has been issued, a WRITE routine must be used. Instead of printf use
  1694. FPRINTF which has the same functions.
  1695.  
  1696. Wait a minute. The FPRINTF is a routine for buffered files and an unbuffered 
  1697. will was opened with OPEN. It only works it the file handle was obtained with 
  1698. FOPEN. Since the handle is an integer value and not a file pointer, the 
  1699. handle doesn't print the FPRINTF. However, the library contains a command
  1700. named SPRINTF. Instead of writing the prepated data into the output of the
  1701. buffer, everything goes to a string. The following example invokes this 
  1702. function :
  1703.  
  1704.     char string[200]; /* Not too small */
  1705.     int test = 4711;
  1706.  
  1707.     sprintf(string,"The result is %5d\n",test);
  1708.  
  1709.                 PAGE 220
  1710.  
  1711. -----------------------------------------------------------------------------
  1712.  
  1713.  
  1714. Now the user can write anything into his own window - the PRINTF function 
  1715. isnt required for output into the CLI window. Now everything needed for
  1716. input / output in the new window is available. Here is the corrected 
  1717. listing :
  1718.  
  1719.     /* window3.c 23.7    */
  1720.     #define ESC 27
  1721.     
  1722.     main()
  1723.     {
  1724.        int dummy = 0, num, handle;
  1725.        char c, line[256];
  1726.  
  1727.        handle = open("RAW:50/50/200/60/My program",0,dummy);
  1728.        printf("Handle %d open\n",handle);
  1729.        if(handle !=-1)
  1730.         {
  1731.            do
  1732.         {
  1733.         num = read(handle, &c, 1);
  1734.         write(handle,&c,1); /* output only the character */
  1735.         sprintf(line,character >%c< Code %d\n",c,c);
  1736.         write(handle,line,strlen(line));
  1737.          } while (c!=ESC);
  1738.          close(handle);
  1739.       }
  1740.     }
  1741.  
  1742.                 PAGE 221
  1743.  
  1744. -----------------------------------------------------------------------------
  1745.  
  1746. 23.8 REDIRECTION
  1747.  
  1748. The operating system controls the redirection of data so the programmer 
  1749. doesn't have to worry about it. The use of standard input/output acts as the
  1750. condition for ensuring data redirection. This includes familiar functions such
  1751. as printf,scanf,putchar,getchar,puts etc....
  1752.  
  1753. Look again at the first RAW: program above which used printf for text output.
  1754. This example will help you understand redirection.
  1755.  
  1756. The "normal" call for programs not expecting arguments is :
  1757.     
  1758.     program_name
  1759.  
  1760. Instructions that are executed by the operating system and not by the program
  1761. can follow the filename. The greater than (>) or less than (<) characters 
  1762. preceed these instructions. The characters inform the operating system that
  1763. the standard input/output should be modified. Here's a practical example:
  1764.  
  1765.     prg <file1 >file2
  1766.  
  1767. The program never sees these two arguments. The operating system reads the 
  1768. standard input from file1 and sends the output to file2. The operating system
  1769. also opens and closes the files automatically. The greater than (>) and less
  1770. than (<) characters indicate the direction of data, as an arrow would indicate
  1771. direction. You can immediately see that the data goes to the filename FILE2.
  1772. Let's examine this process using the window2.c RAW program in the previous
  1773. section. The PRINTF can be redirected so that all text goes to a file or 
  1774. printer (PRT:). Start the program (called window2 here) with the following 
  1775. line :
  1776.  
  1777.     window2 > output.data
  1778.  
  1779. The new window appears again but no keypresses seem to affect the window. 
  1780. That's all right, since the output which would otherwise appear in the CLI 
  1781. window now goes to the file OUTPUT.DATA. After typing on the keyboard for a 
  1782. while press the <Esc> key. The window dissappears and the user returns to CLI.
  1783. The OUTPUT.DATA file can now be read using the ED or TYPE commands.
  1784.  
  1785. Input can also be redirected from the keyboard to a file. This is how a MAKE
  1786. file could be created. In these programming examples this wouldnt make sense
  1787. since you dont read from the standard input. A redirection would not make 
  1788. much sense in this case.
  1789.  
  1790.                 PAGE 222
  1791.  
  1792. -----------------------------------------------------------------------------
  1793.  
  1794. The standard input / output is a normal line. Just as in opening a file, a 
  1795. file handle is returned. Since these lines are always open, the programmer 
  1796. doesnt have to worry about them. There are of course variables for there 
  1797. handles. They are:
  1798.  
  1799.     stdin
  1800.     stdout
  1801.     stderror
  1802.  
  1803. The STDIN variable represents "standard input" and the STDOUT variable 
  1804. represents "standard output". Whats the third ?
  1805.  
  1806. In addition to the input and output of "normal" information C offers an error
  1807. channel. This makes sense in the following situation.
  1808.  
  1809. As described above, the information is redirected. Because an error occurred 
  1810. in the input (e.g. a non-existant input file) an error message appears on the
  1811. screen. Wait, the standard output was written to an other file. This would
  1812. mean that the error message was written to the file and the user might not
  1813. know about this error. For this reason error messages use a separate channel
  1814. to display user messages.
  1815.  
  1816. All three variables (STDIN,STDOUT and STDERROR) can be used as file pointers
  1817. which are returned through FOPEN.
  1818.  
  1819. CAUTION :
  1820.  
  1821. These buffered input / output routines should not be confused with the 
  1822. unbuffered ones. Permitted functions with the file pointers above would be
  1823. fprintf,fwrite,fread etc...
  1824.  
  1825. The definition of GETCHAR can be found in the file STDIO.H under :
  1826.     
  1827.     getc(stdin)
  1828.  
  1829.                 PAGE 223
  1830.  
  1831. -----------------------------------------------------------------------------
  1832.  
  1833.                      CHAPTER 24 - TRICKS AND TIPS
  1834.  
  1835.  
  1836. During programming unexpected errors can sometime occur. For a novice
  1837. programmer, the reasons for these problems can be very hard to find. Much
  1838. work is often required to determine whether the source of the problem is in
  1839. the source code. the compiler or the operating system. This chapter has a
  1840. few hints for helping you find those errors.
  1841.  
  1842. You'll find that this chapter contains a number of tips and tricks for C
  1843. programming on the Amiga. These tips include the creation of C programs
  1844. that are accessible from the workbench preporcessor directives and macros.
  1845.  
  1846.  
  1847. 24.1 STARTING FROM THE WORKBENCH.
  1848.  
  1849. You may have already tried to start you own programs from the Workbench.
  1850. Prehaps you wondered why, depsite a full disk, nothing appears in that
  1851. drawer's window. The reason for this is that every visible program has an
  1852. extra file used for storing the programs information and icon data. Every
  1853. program which appears in a workbench window has a file with the extension
  1854. of .INFO .
  1855.  
  1856. Our C program also need .INFO files before they can be accessed from the
  1857. Workbench. Select a suitable icon from the Workbench (the clock or notepad
  1858. for example). Any other icon cn be selected for this program. Now enter the
  1859. CLI. Copy only the source .info file to an .info file for your file.
  1860. Remeber to use the .info extension for both files in this command. The
  1861. example below copies the notepad.info file to a new .info file for the file
  1862. test_workb:
  1863.  
  1864.         copy notepad.info test-workb.info
  1865.  
  1866. Change test-workb to your own filename, and remeber to keep the .info
  1867. extension on both filenames.
  1868.  
  1869. Quit the CLI. Click the disk icon containing the target file and .info file
  1870. to display the icon. If the icon is covering another icon move it to a free
  1871. location in the window. Click once on the icon. Press a <shift> key and
  1872. click on a disk icon. Select SNAPSHOT from the special menu to save the new
  1873. position.
  1874.  
  1875. The following program will tell you how it was accessed, from the workbench
  1876. or from the CLI.
  1877.  
  1878.                                 PAGE 227
  1879.  
  1880. ---------------------------------------------------------------------------
  1881.  
  1882.         /* access.c 24.1 */
  1883.  
  1884.         #include "stdio.h"
  1885.  
  1886.         main(argc,argv)
  1887.         int argc;
  1888.         char *argv[];
  1889.         {
  1890.           int dummy = 0, handle;
  1891.           char line[256];
  1892.  
  1893.           if(argc) /* Argument numberr not zero */
  1894.            {
  1895.            handle = open("RAW:50/50/200/60/my program",0,dummy);
  1896.              if(handle !=-1) /* no error on opening */
  1897.               {
  1898.                 sprintf(line,"started from CLI!\n");
  1899.                 write(handle,line, strlen(line));
  1900.                 while(--argc >= 0)
  1901.                   {
  1902.                     write(handle, *argv, strlen(*argv));
  1903.                       argv++;
  1904.                   }
  1905.                 read(handle,line,1); /* Wait for keypress */
  1906.                 close(handle);
  1907.               }
  1908.             else
  1909.               fprintf(stderr,"\nError in opening window\n");
  1910.            }
  1911.          else
  1912.            {
  1913.              printf("Started from the Workbench!\nRETURN-KEY\n);
  1914.              getchar();
  1915.            }
  1916.         }
  1917.  
  1918. It is important that the programmer knows whether the program started from
  1919. workbench or CLI. The argument counter ARG senses this. If arg=0, the user
  1920. started the program from the workbench. Consider the possible values in the
  1921. CLI. As a minimum argc contains a 1 only when the program name was used
  1922. during the call without additional arguments. Otherwise this variable is
  1923. incremented by the number of parameters. The 0 is an ideal method of
  1924. differentiation between the two calls. The big question "Who cares where
  1925. the program started ? ".
  1926.  
  1927. Start the program window2 from the previous chapter which opens a window.
  1928. The workbench creates an additional, useless window. One window is used,
  1929. the other remains empty. There must be an option of sensing a program
  1930. started from the workbench or from the CLI.
  1931.  
  1932. In the first case you get a window automatically and the standard
  1933. input/output is automatically directed to this window. The basic functions
  1934. such as scanf and printf can be used and you can still enjoy the use of
  1935. your window. In the second case the user must handle his own window and
  1936. input/output.
  1937.  
  1938.                                 PAGE 228
  1939.                                 
  1940. ---------------------------------------------------------------------------
  1941.  
  1942.  
  1943. 24.2 OTHER PREPROCESSOR DIRECTIVES.
  1944.  
  1945. The directives #define and #include should be familiar to you by now.
  1946. Preprocessor directives make the programmer's work easier. The most
  1947. important are the following :
  1948.  
  1949.         #undef MACRO.
  1950.  
  1951. UNDEFINING:
  1952.  
  1953. This is the opposite of #define. This undefines (cancels) the macro
  1954. definition. Assume that two #define directives had been used as follows:
  1955.  
  1956.         #define EOS 0
  1957.          . . . . .
  1958.         #define EOS '/0'
  1959.  
  1960. Any subsequent program sections use the most recent definition of EOS. The
  1961. first assignment is ignored for the moment. This process canbe compared
  1962. with local variables which use the same name. Access can only occur to the
  1963. last variable (definition) defined. If the definition is reversed with
  1964. #undef, for example:
  1965.  
  1966.         #undef EOS
  1967.  
  1968. the defined EOS is still present, but now with the first assignment (0).
  1969.  
  1970.  
  1971. PARTIAL COMPILATION :
  1972.  
  1973. The following directive permits the compilation of certain portions of a
  1974. file, depending on the macro that was defined:
  1975.  
  1976.         #ifdef MACRO
  1977.  
  1978. Should the macro be defined, the following portion is processed by one of
  1979. these two preprocessor directives :
  1980.  
  1981.         #elseif MACRO
  1982.         #endif  MACRO
  1983.  
  1984. If the macro is unknown at this point, all lines are skipped up to the
  1985. following directives. If an #elseif appears the subsequent source code is
  1986. compiled up to the #endif.
  1987.  
  1988. These directives are comparable to the C commands:
  1989.  
  1990.         if()
  1991.           {
  1992.           . . . .
  1993.           }
  1994.         else
  1995.           {
  1996.            . . . 
  1997.           }
  1998.                                 PAGE 229
  1999.  
  2000. ----------------------------------------------------------------------------
  2001.  
  2002.  
  2003. The commands themselves have nothing to do with the final code. The
  2004. reversal of this makes the following line possible :
  2005.  
  2006.         #ifndef MACRO
  2007.  
  2008. Here the macro cannot be defined, so the part following can be compiled.
  2009. Certain parts of a file can be included or left out through the setting of
  2010. a #define, without changing the file to a great extent. Where are the
  2011. directives used ?
  2012.  
  2013. In programs intended for compilation on other compilers or even other
  2014. computers, some differences must be considered such as compiler errors. To
  2015. achieve an error free compiler run, a DEFINE can indicate the compiler
  2016. type. These directives can be found in some header files which come with
  2017. the compilers.
  2018.  
  2019.  
  2020.                                 PAGE 230
  2021.  
  2022. ----------------------------------------------------------------------------
  2023.  
  2024.  
  2025. 24.3 FINDING AND REMOVING ERRORS.
  2026.  
  2027. No program, in the initial stages of development, is free of either syntax
  2028. or logical errors. The compiler calls these syntactical problems to your
  2029. attention. Removing these errors shouldn't be a problem. This section
  2030. describes a few of the possible meaning behind these errors.
  2031.  
  2032.         . Missing semicolon
  2033.  
  2034. If the semicolon is not missing in the line indicated, check one or two
  2035. lines above the line stated by the compiler and check the level of
  2036. parenthesis.
  2037.  
  2038.         . Braces do not Agree
  2039.  
  2040. This error often requires a search of the whole area preceeding the error.
  2041. If you omitted a brace somewhere, the following part is added to the
  2042. function described up to this point. This in turn leads to mysterious error
  2043. messages, for example the missing semicolon in the next function
  2044. definition.
  2045.  
  2046.         . Wrong Answers
  2047.  
  2048. If a function which executes flawlessly suddenly returns wrong results, the
  2049. error may be caused by a failure to declare the function (not for INT). For
  2050. this reason all functions not having a return value of INT should be
  2051. declared globally at the beginning of the file. The global declaration
  2052. keeps newly added functions, which also use this routine, from erroring
  2053. out. Complex formulas which work with various operators and data types
  2054. should generally be in parentheses. This not only makes them more visible,
  2055. but also prevents errors. Nobody knows all the priorities of various
  2056. operators by heart and this can quickly lead to problems if a mistake is
  2057. made. It is better to use one parenthesis too many than one too few.
  2058.  
  2059.         . Easily confused character combinations.
  2060.  
  2061. Even experience programmers have misread these characters :
  2062.  
  2063.         == and =
  2064.         && and &
  2065.         || and |
  2066.  
  2067. Watch for the legal maximum values of the various data types in
  2068. calculations. They may differ from one compiler to another.
  2069.  
  2070.                                 PAGE 231
  2071.  
  2072. ----------------------------------------------------------------------------
  2073.  
  2074.         char -128 to 127
  2075.         int -32767 to 32766
  2076.         long -2,147,483,648 to 2,147,483,647
  2077.         float -10**38 to 10**38
  2078.         double -10**303 to 10**303
  2079.  
  2080. These can never be exceeded, even in intermediate results of a long
  2081. equation such as :
  2082.  
  2083.         i = (x * y * z-z) / y-x;
  2084.  
  2085. This can happen quickly with x*y*z if the three factors contain large
  2086. numbers.
  2087.         
  2088.         .System crash
  2089.  
  2090. This may have many causes, for example:
  2091.  
  2092.         Pointer not initialised.
  2093.         Wrong parameter passed (wrong data type).
  2094.         Pointer access to old address (except for char pointer).
  2095.  
  2096.                                 PAGE 232
  2097.  
  2098. ----------------------------------------------------------------------------
  2099.  
  2100.                         CHAPTER 25 - SYSTEM PROGRAMMING
  2101.  
  2102. One of the reasons people work with the C language is because of it's
  2103. speed. The main reason Amiga owners use C is probably because the Amiga's
  2104. operating system was written in C. Knowing the peculiarities of C often
  2105. helps you understand the Amiga's operating system. This is especially
  2106. noticeable during system programming when you try to get more performance
  2107. from the computer.
  2108.  
  2109. INTUITION:
  2110.  
  2111. This chapter takes you into the world of intuition. Intuition is the
  2112. section of the operating system that is concerned with windows, screens,
  2113. icons, gadgets, menus and the mouse. Intuition's capabilities are so vast
  2114. that we can explore only a small portion of this material. Youll find
  2115. additional references suggested if you wish to explore further. We chose to
  2116. limit ourselves to introductory material on Intuition, especially the
  2117. creation of windows and screens.
  2118.  
  2119. One small warning in advance: Intuition is very complex. Youll see this
  2120. from the C source that follow in this chapter - the source codes are much
  2121. more complicated than the ones youve seen so far. Even if you dont
  2122. understand everything , you should try the programs and experiment with
  2123. them.
  2124.  
  2125. 25.1  THE INTUITION PRINCIPLE.
  2126.  
  2127. To use intuition in use programs, some conventions must be followed. For
  2128. example, Intuition routines can only be used once the intuition library has
  2129. been opened. Intuition is simply a large library containing the functions
  2130. used in connection with windows and similar things. The difference from the
  2131. C libraries presented up to now is that these routines are not linked
  2132. during linking. The user relies on the fact that they are stored somewhere
  2133. in the computer and are available during program execution. This has some
  2134. advantaged. Since many programs use the same intuition routines, they dont
  2135. have to be stored several times in the memory. Every program can use the
  2136. routines for its own purposes, even if they work with other programs in
  2137. memory (multitasking). This save working memory. It makes no difference
  2138. where these routines are stored in memory. When you open the
  2139. INTUITION.LIBRARY, a pointer is returned to the beginning of this function
  2140. list. A trademark of intuition programming is a lot of pointers and
  2141. structures.
  2142.  
  2143.                                 PAGE 235
  2144.  
  2145. ----------------------------------------------------------------------------
  2146.  
  2147. 25.2  A WINDOW UNDER INTUITION.
  2148.  
  2149. We displayed a window on the screen the the normal OPEN function. This
  2150. functions lets the user select the size and position in advance, and
  2151. permits window sizing and movement. However, intuition offers special
  2152. features for windows. Lets look at the required structure which contains
  2153. all the important information for the window:
  2154.  
  2155.         struct NewWindow
  2156.         {
  2157.           SHORT LeftEdge,TopEdge;
  2158.           SHORT Width, Height;
  2159.           UBYTE DetailPen, BlockPen;
  2160.           ULONG IDCMPFlags;
  2161.           struct Gadget *FirstGadget;
  2162.           struct Image *CheckMark;
  2163.           UBYTE *Title;
  2164.           struct Screen *Screen;
  2165.           struct BitMap *BitMap;
  2166.           SHORT MinWidth, MinHeight;
  2167.           SHORT MaxWidth, MaxHeight;
  2168.           USHORT Type;
  2169.         }
  2170.  
  2171. THE NEWWINDOW STRUCTURE :
  2172.  
  2173. The structure definition can be found in the header file
  2174. intuition/intuition.h. Now let's filter out the items that we are really
  2175. going to use. The name is already remarkable: NewWindow. The same file
  2176. usually contains a structure named Window. You need the NewWindow structure
  2177. to define a new user window.
  2178.  
  2179. The first four entries represent the upper left corner and the windows
  2180. dimensions in height and width. These are the same values as those used in
  2181. the CLI's Open command:
  2182.  
  2183.         open("CON:20/40/200/50/windowtitle",0,0);
  2184.  
  2185. To use the same values for the intuition window, the values are assigned to
  2186. the structure components. The following definition preceeds the window
  2187. description :
  2188.  
  2189.         struct NewWindow NewWindow;
  2190.  
  2191.         ....
  2192.  
  2193.         NewWindow.LeftEdge = 20;
  2194.         NewWindow.TopEdge  = 40;
  2195.         NewWindow.Width = 200;
  2196.         NewWindow.Height = 50;
  2197.  
  2198.                                 PAGE 236
  2199.  
  2200. -----------------------------------------------------------------------------
  2201.  
  2202.  
  2203. The capabilities a CLI OPEN command cant provide are colour settings for
  2204. the window.
  2205.  
  2206. The values in DetailPen specify the window title and the height of the
  2207. title bar. The number describes the colour register index. If 4 possible
  2208. colour are available, they are numbered from 0 to 3. The colors cannot be
  2209. changed because they're determined by the settings in preferences. The
  2210. background always occupies register 0. The BlockPen register draws the
  2211. color for the window's border.
  2212.  
  2213.  
  2214. 25.2.1 THE WINDOW FLAGS :
  2215.         
  2216. The next entry (IDCMPFlags) will be skipped since it isn't used. The
  2217. element Flags in the NewWindow structure determine certain items in the
  2218. window, which are set with DEFINES. Every define determines whether or not
  2219. an intuition function is required (e.g. WINDOWSIZING). Look at the defines
  2220. used in the sample program:
  2221.  
  2222. There are many more useful defines included for windows:
  2223.  
  2224. SMART_REFRESH:
  2225.  
  2226. This causes the Amiga to control and store everything concerning window
  2227. changes and contents. If another window is dragged over the user window, a
  2228. part of window may be temporarily obscured. The computer automatically
  2229. stores this area in a buffer and, if needed, will restore it again.
  2230.  
  2231. ACTIVATE :
  2232.  
  2233. This automatically activates the window once it is opened. This saves the
  2234. user the trouble of clicking the window to activate it.
  2235.  
  2236. WINDOWSIZING:
  2237.  
  2238. Permits a window with a size gadget to change dimensions. By selecting this
  2239. DEFINE, the gadget appears in the lower right corner of the window. The
  2240. operating system keeps watch over this gadget for any activity.
  2241.  
  2242. WINDOWDRAG : The window can be moved.
  2243.  
  2244. WINDOWDEPTH:
  2245.  
  2246. The window can be moved in front of or behind other windows with the front
  2247. and back gadgets (the gadgets in the upper right corner). The operating
  2248. system keeps watch over these gagets for any activity.
  2249.  
  2250. NOCAREREFRESH :
  2251.  
  2252. Practically anything that occurs during program execution can selectivley
  2253. generate a message from the operating system. If you want a message
  2254. displayed when you try resizing a window, you can generate one. For
  2255. example, when editing a text using ED, the text file must be updated when
  2256. the window changes size. The program gets the message that the window must
  2257. be brought to the current condition. With the DEFINE above, the operating
  2258. system is told that no such message is desired. The message is not needed
  2259. since SMART_REFRESH takes care of all the update work when active.
  2260.  
  2261.                                 PAGE 237
  2262.                                 
  2263. ----------------------------------------------------------------------------
  2264.  
  2265. Of the remaining elements of the NewWindow structure, only Title and the
  2266. last five are of interest. As the name implies the title is placed into the
  2267. title bar at the top of the window. The following program demonstrates that
  2268. only the address of the string is assigned:
  2269.  
  2270.         NewWindow.Title = "The user window";
  2271.  
  2272. If no constants are used as in the example, the memory space must be
  2273. prepared by the user and it's beginning assigned to the entry Title.
  2274.  
  2275. The values MinWidth,MinHeight,MaxWidth,MaxHeight indicate the minimum and
  2276. maximum values for the user window. The user cannot go beyond these
  2277. limitations. Since the maximum height of a window is 200 or 400 pixels,
  2278. these numbers are used more frequently. PAL versions of the Amiga can
  2279. create a maximum height of 256 or 512 pixels, depending on the mode
  2280. selected.
  2281.  
  2282. Finally, WBENCHSCREEN is entered into the element TYPE so that the
  2283. parameters preset by workbench can be used.
  2284.  
  2285.  
  2286. 25.2.2 OPENING A WINDOW.
  2287.  
  2288. After this preliminary work, the window can finally be opened. The
  2289. OpenWindow function opens the window and returns a pointer. This pointer
  2290. points to a window structure but shouldnt be confused with NewWindow. It is
  2291. more comprehensive than NewWindow and can be examined in INTUITION.H.
  2292.  
  2293. The OPENWINDOW function requires the address of the newwindow structure as
  2294. the parameter. Since many compilers permit the passing of whole structures,
  2295. the following expression can be used to determine the address :
  2296.  
  2297.         &NewWindow
  2298.  
  2299. If everything was processed properly, the new window will have the
  2300. specifications which were entered in NewWindow.
  2301.  
  2302. The CLOSEWINDOW function is all you need to close the window again (e.g.,
  2303. when the program is finished). It has the window pointer as it's only
  2304. parameter. The window dissappears again.
  2305.  
  2306. Finally the intuition library closes to leave everything the way it was
  2307. found. If you close intuition before closing the last window, the Guru
  2308. Meditiation appears.
  2309.  
  2310.                                 PAGE 238
  2311.  
  2312. -----------------------------------------------------------------------------
  2313.  
  2314.  
  2315. 25.2.3 A WINDOW PROGRAM :
  2316.  
  2317. This listing describes a large amount of theory. The program opens a window
  2318. which can be moved, sized and moved to the front or back. Watch uppercase
  2319. and lowercase letters in this listing.
  2320.  
  2321.         /* Window intuition.c   25.2.3  */
  2322.         
  2323.         #include <exec/types.h>
  2324.         #include <intuition/intuition.h>
  2325.  
  2326.         extern struct Window *OpenWindow();       /* Delcaration */
  2327.         extern long *OpenLibrary();     /* Hello Aztec user */
  2328.         struct IntuitionBase *IntuitionBase;
  2329.  
  2330.         #define INTUITION_REV 0
  2331.  
  2332.         main()
  2333.         {
  2334.            struct NewWindow NewWindow;
  2335.            struct Window *Window;
  2336.            long i;
  2337.  
  2338.            IntuitionBase = (struct IntuitionBase *)
  2339.              OpenLibrary("intuition.library",INTUITION_REV);
  2340.  
  2341.            if(IntuitionBase == NULL)
  2342.              exit(FALSE);
  2343.  
  2344.            NewWindow.LeftEdge = 20;
  2345.            NewWindow.TopEdge = 20;
  2346.            NewWindow.Width = 200;
  2347.            NewWindow.Height = 80;
  2348.            NewWindow.DetailPen = 0;
  2349.            NewWindow.BlockPen = 2;
  2350.            NewWindow.IDCMPFlags = NULL;
  2351.            NewWindow.Flags = SMART_REFRESH | ACTIVATE |
  2352.               WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | 
  2353.               NOCAREREFRESH;
  2354.            NewWindow.FirstGadget = NULL;
  2355.            NewWindow.CheckMark = NULL;
  2356.            NewWindow.Title = (UBYTE *)"The User Window";         
  2357.            NewWindow.Screen = NULL;
  2358.            NewWindow.BitMap = NULL;
  2359.            NewWindow.MinWidth = 80;
  2360.            NewWindow.MinHeight = 25;
  2361.            NewWindow.MaxWidth = 640;
  2362.            NewWindow.MaxHeight = 200; /* PAL = 256 */
  2363.            NewWinndow.Type = WBENCHSCREEN;
  2364.  
  2365.            if((Window= OpenWindow(&NewWindow))==NULL)
  2366.              exit(FALSE);
  2367.  
  2368.            for(i=0;i<=800000,i++) /* small pause */
  2369.              ;
  2370.  
  2371.            CloseWindow(Window);
  2372.            CloseLibrary(IntuitionBase);
  2373.            exit(TRUE);
  2374.         }
  2375.  
  2376.                                 PAGE 239
  2377.  
  2378. ----------------------------------------------------------------------------
  2379.  
  2380.  
  2381. The program above exactly follows the indications and requirements
  2382. previously stated. First the intuition library opens. If this is not
  2383. possible for some reason a 0 is returned as an intuition pointer.
  2384. Continuing would make no sense at that point so the program will end. The
  2385. window pointer returned can be null so it must be tested.
  2386.  
  2387. Examine the declaration of the OPENWINDOW function at the beginning of the
  2388. listing. This not only preserves a good C style, but also the suppresses
  2389. the changing of returned values with the CAST statement. For example, this
  2390. is the case in the OpenLibrary because the routine returns not only the
  2391. intuition pointer but also a variety of other pointer types. Nevertheless
  2392. the function should be declared at least as a routine which returns
  2393. pointers. This prevents, for example, the Aztec system crashes which result
  2394. from not declaring the function. This means that, for the compiler, integer
  2395. values will be delivered which in Aztec are only 2 bytes long. It should be
  2396. obvious that the value with 4 bytes does not arrive. Only 2 bytes will be
  2397. accepted.
  2398.  
  2399. The CAST statement STRUCT INTUITIONBASE * can be used to trick the best
  2400. compiler. Most of the time the resulting value isnt equal to 0 and doesnt
  2401. cause the system to crash. During the next access to a library function
  2402. with the INTUITIONBASE pointer, the system crashes. This accident cannot
  2403. occur with the Lattice C compiler since it's integers always use 4 bytes.
  2404.  
  2405. During the opening of the library, the routine wants a version number which
  2406. is required for proper processing. If the system has the same or later
  2407. version, everything proceeds smoothly. Since this program has no special
  2408. needs, a 0 is selected.  
  2409.  
  2410. While opening the window, the address of the NewWindow structure is passed.
  2411. The system then accepts the data in an internal area so that even this
  2412. variable, NewWindow is no longer required. If something is done to the
  2413. window, it can be done with the window structure.
  2414.  
  2415. If the compilation displays warning messages, don't be alarmed. Some
  2416. structures need definition which are not used explicitly but appear in a
  2417. structure definition as sub-elements. Maybe the functions required can be
  2418. included with include. This may also result in additional unknown
  2419. structures surfacing which also want to be defined. The only solution is to
  2420. define all functions with include. This requires an enormous amount of
  2421. memory space, and increases compiler time significantly. Unless the user
  2422. has a RAM disk on which all include files are stored, it is not advisable
  2423. to do this because nothing changes in the object code anyway.
  2424.  
  2425.                                 PAGE 240
  2426.  
  2427. ----------------------------------------------------------------------------
  2428.  
  2429.  
  2430. After the general framework of the window program has been constructed,
  2431. some experimentation is helpful. Change a few values in the NewWindow
  2432. structure to see the effect on the window. Leave the unknown structure
  2433. entries and the type element untouched.
  2434.  
  2435. Under intuition, it's impssible to exhaust the topic of windows. The user
  2436. who wants to know more should obtain more literature on this subject.
  2437.  
  2438.                                 PAGE 241
  2439.  
  2440. ----------------------------------------------------------------------------
  2441.  
  2442.                  
  2443. 25.3 SCREENS.
  2444.  
  2445. A screen is simply a CRT (Cathode Ray Tube) display. In most PCs and home
  2446. computers, only one screen shows the screen contents. The Atari ST and
  2447. Amiga screens can display several windows at a time.
  2448.  
  2449. The Workbench screen is already familiar to you. Any number of windows can
  2450. be opened on any screen, depending on the amount of memory available. It
  2451. also determines the number of colours available and the colour composition
  2452. available to be used by the windows. The workbench generally offers 4
  2453. different colours and works with a resolution of 640*400 pixels (640*512
  2454. pixels in PAL systems).
  2455.  
  2456. The user can specifiy these values for each program in order to construct a
  2457. screen to personal taste. The number of colours depends on the number of
  2458. available bit-planes. A bit-plane represents a part of memory which is used
  2459. for storing graphics. More memory permits more bit-planes and therefore
  2460. more colours. The workbench uses two bit-planes for 4 colours. A table
  2461. illustrates the connection between colorsa and bitplanes.
  2462.  
  2463.         Number of bit-planes            Number of Colors.
  2464.         ------------------------        -----------------
  2465.                 1               ->              2
  2466.                 2               ->              4
  2467.                 3               ->              8
  2468.                 4               ->             16
  2469.                 5               ->             32 (not always possible).
  2470.  
  2471. Not only can the number of colours be selected, but also the resolution of
  2472. the screen. You can reach a maximum of 32 colours and a resolution of
  2473. 640*400 pixels (640*512 in PAL systems). As in the window, two colour
  2474. registers canbe assigned, which are responsible for the borders and the
  2475. background. Since these values which are stored in the NewScreen structure
  2476. stongly remind you of the NewWindow structure, let's look at the structure
  2477. definition.
  2478.  
  2479.         struct NewScreen
  2480.         {
  2481.           SHORT LeftEgde,TopEdge,Width,Height,Depth;
  2482.           UBYTE DetailPen,BlockPen;
  2483.           USHORT ViewModes;
  2484.           USHORT Type;
  2485.           struct TextAttr *Font;
  2486.           UBYTE *DefaultTitle;
  2487.           struct Gadgets *Gadgets;
  2488.           struct BitMap *CustomBitMap;
  2489.         }
  2490.  
  2491.                                 PAGE 242
  2492.  
  2493. ----------------------------------------------------------------------------
  2494.  
  2495.  
  2496. The first entries in this structure have the same names as those in
  2497. NewWindow. They also have exactly the same meanings. DEPTH indicates the
  2498. number of bit-planes (1-5), which were already discussed. DetailPen and
  2499. BlockPen are the colour indices. They depend on the number of available
  2500. bit-planes.
  2501.  
  2502. The next important entries are TYPE (the CUSTOMSCREEN must be set here) and
  2503. DEFAULTTITLE which points to the title line of the screen. This is enough
  2504. for the user program to fully define a screen.
  2505.  
  2506. The beauty of intuition is that everything follows a certain pattern so
  2507. that many different problems can be solved in the same manner. After
  2508. understanding how to create a window, it shouldn't be a problem to create a
  2509. screen on the monitor. First the NewWcreen structure is stored in the
  2510. manner described above. Then the screen is opened with the following
  2511. function :
  2512.  
  2513.         Screen = OpenScreen(&NewScreen);
  2514.  
  2515. The variable Screen represents a pointer to the structure named screen.
  2516. Also, the structures NewWscreen and Screen must be differentiated here.
  2517. NewScreen is only required once for the OpenScreen function. The data is
  2518. transferred to the Screen structure (the Screen structure is much more
  2519. comprehensive than the NewScreen structure). A pointer to the new screen
  2520. structure is the return value.
  2521.  
  2522. To open a window to this screen, the initialisation of the NewWindow
  2523. structure must be changed slightly. The TYPE in the define WBENCHSCREEN is
  2524. replaced by CUSTOMSCREEN. The entry screen must be supplied with a Screen
  2525. pointer. The define CUSTOMSCREEN indicates that the window to the user
  2526. screen should be opened. The window gets all the capabilities offered by
  2527. the screen. Since several screens can be opened by a program, the window
  2528. must be attached to a specific screen. This assignment can only be made
  2529. after the screen has already been opened and the screen pointer is
  2530. available.
  2531.  
  2532. Before the program ends, the screen is closed is closed with CloseScreen to
  2533. which the screen pointer is passed. The window must be closed before the
  2534. screen, or serious problems will occur.
  2535.  
  2536.                                 PAGE 243
  2537.  
  2538. -----------------------------------------------------------------------------
  2539.  
  2540.  
  2541. The listing for the subject of screens has some more enhancements which
  2542. will be explained now :
  2543.  
  2544.         /* Screen_intuition.c   25.3.1  */
  2545.  
  2546.         #include <exec/types.h>
  2547.         #include <intuition/intuition.h>
  2548.  
  2549.         extern LONG OpenLibrary();
  2550.         extern struct Screen *OpenScreen();
  2551.         extern struct Window *OpenWindow();
  2552.  
  2553.         struct IntuitionBase *IntuitionBase;
  2554.  
  2555.         #define INTUITION_REV 0
  2556.  
  2557.         struct NewScreen NewScreen =
  2558.         {
  2559.           0,0,
  2560.           640,  /* width */
  2561.           200,  /* height */
  2562.           3,    /* 3 bitplanes = 8 colours */
  2563.           3,5,  /* Another colour combination */
  2564.           HIRES,
  2565.           CUSTOMSCREEN,
  2566.           NULL,
  2567.           "To end the program, please click Close Gadget!",
  2568.           NULL,
  2569.           NULL,
  2570.         };
  2571.  
  2572.         struct NewWindow NewWindow = 
  2573.         {
  2574.           40,40,        /* X and Y position */
  2575.           280,120,      /* Width, Height        */
  2576.           4,6,          /* Colours 0 - 7        */
  2577.           CLOSEWINDOW,
  2578.           WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWSIZING |
  2579.           SIZEBRIGHT | WINDOWDRAG | WINDOWDEPTH,
  2580.           NULL,
  2581.           NULL,
  2582.           "**** HELLO ****",
  2583.           NULL,
  2584.           NULL,
  2585.           190,20,
  2586.           640,200,  /* IN PAL CHANGE 200 TO 256 */
  2587.           CUSTOMSCREEN
  2588.         };
  2589.  
  2590.         main()
  2591.         {
  2592.           struct Screen *Screen;
  2593.           struct Window *Window;
  2594.  
  2595.           if((IntuitionBase = (struct IntuitionBase *)
  2596.            OpenLibrary("intuition.library",INTUITION_REV))==NULL)
  2597.              exit(FALSE);
  2598.         
  2599.           if((Screen = OpenScreen(&NewScreen))==NULL)
  2600.              exit(FALSE);
  2601.  
  2602.           NewWindow.Screen = Screen; /* DO NOT FORGET THIS !!!! */
  2603.  
  2604.           if((Window = OpenWindow(&NewWindow))==NULL)
  2605.              exit(FALSE);
  2606.  
  2607.           /* Wait for Close Gadget      */
  2608.           Wait(1 << Window->UserPort->mp_SigBit);
  2609.  
  2610.           printf("\nLast window Values: %d/%d/%d/%d\n\n",
  2611.                 Window->LeftEdge,
  2612.                 Window->TopEdge,
  2613.                 Window->Width,
  2614.                 Window->Height);
  2615.  
  2616.           CloseWindow(Window); /* Close Everything in sequence  */
  2617.           CloseScreen(Screen);
  2618.           CloseLibrary(IntuitionBase);
  2619.           exit(TRUE);
  2620.         }
  2621.  
  2622.                                 PAGE 244
  2623.  
  2624. ---------------------------------------------------------------------------
  2625.  
  2626.  
  2627. Since C programmers are usually too lazy to type, structure initialisation
  2628. is best performed during the definition of the variables. Another
  2629. innovation is the entry of the CLOSEWINDOW in the IDCMPFlags. In
  2630. combination with the WINDOWCLOSE in Flags, the close gadget can be tested.
  2631. The WAIT statement tells the system to wait for the activities entered in
  2632. the IDCMP flags:
  2633.  
  2634.         Wait( 1 << Window->UserPort->mp_SigBit);
  2635.  
  2636. Clicking the close gadget is the only way out. As in the window program all
  2637. flags are set,  which permit the user to change the size and position of
  2638. the window. The window pointer points to the desired elements LeftEdge,
  2639. TopEdge, Width and Height.
  2640.  
  2641. Although the example program above uses three bit-planes, the maximum
  2642. accessible colours is 8. Therefore, the colour registers can be from 0 to
  2643. 7. Experimenting with screens takes up a lot of memory. The program above
  2644. requires almost 80K or RAM.
  2645.  
  2646.                                 PAGE 245
  2647.  
  2648. ---------------------------------------------------------------------------
  2649.  
  2650.  
  2651. 25.4  TEXT/GRAPHIC WINDOW DISPLAY.
  2652.  
  2653. Intuition sees little difference between processing text or graphics. Since
  2654. a printf call doesn't work in intuition windows something else must be
  2655. used.
  2656.  
  2657. 25.4.1 TEXT:
  2658.  
  2659. The TEXT function handles string output. A pointer to a RastPort structure
  2660. passes the text to the window structure. The user doesnt have to know the
  2661. appearance of RastPort or what function it performs. It is enough to passs
  2662. the expression to the responsible routine :
  2663.  
  2664.         Window->RPort
  2665.  
  2666. TEXT requires a character string and it's length as additional parameters.
  2667. The format is as follows :
  2668.  
  2669.         Text(Window->RPort,string,length);
  2670.  
  2671.  
  2672. 25.4.2 MOVE:
  2673.  
  2674. The string passed by text appears at the current cursor position. The MOVE
  2675. function sets this position using this syntax :
  2676.  
  2677.         Move(Window->RPort, xpos, ypos);
  2678.  
  2679. Before each call of the TEXT function, MOVE should position the cursor. A
  2680. small routine for this task follows:
  2681.  
  2682.         text(w_ptr,s,x,y)
  2683.         struct Window *w_ptr;
  2684.         char *s;
  2685.         int x,y;
  2686.         {
  2687.            Move(w_ptr->RPort, x, y);
  2688.            Text(w_ptr->RPort, s, strlen(s));
  2689.         }
  2690.  
  2691.                                 PAGE 246
  2692.  
  2693. ----------------------------------------------------------------------------
  2694.  
  2695. To keep the function generic, the pointer to the window in which the text
  2696. should appear is passed. Because of this you can service several windows
  2697. with the same function. A call appears as follows:
  2698.  
  2699.         text(Window, "Attention!", 20, 40);
  2700.  
  2701. The text appears at position (20/40), if the window will allow it (the IF
  2702. is important). You can write a much text as you wish in the window.
  2703. Intuition ensures that no window or screen is overwritten. If the text
  2704. can't be displayed completely in the window, the writing stops at the
  2705. window's right border. The user can be assured that nothing is accidentally
  2706. drawn in other windows.
  2707.  
  2708.  
  2709. 25.4.3 DRAW :
  2710.  
  2711. The DRAW function draws lines. The parameters of the routine are:
  2712.  
  2713.         Draw(Window->RPort, x, y);
  2714.  
  2715. Sonething's missing here- you need two points to draw a line. With Draw,
  2716. the straight line os drawn between the current position and the (x/y)
  2717. point. The DRAW function belongs to the graphics.library instead of
  2718. intuition.library. First this library must be opened then it returns a
  2719. special pointer.
  2720.  
  2721. For drawing, the mouse co-ordinates are normally needed. They are found in
  2722. mouseX and mouseY which are two elements of the window structure. This
  2723. includes everything needed to write into a window. 
  2724.  
  2725. In the following program argv and argc re-appear. These other values can be
  2726. used from the CLI rather than the preset values. The call has the following
  2727. format :
  2728.  
  2729.         prg X-RES Y-RES BITPLANES
  2730.  
  2731. for example
  2732.  
  2733.         draw 640 200 3
  2734.  
  2735. It is interesting here that the resolution of a screen can be larger than
  2736. the maximum resolution of the display monitor. 640*200 pixels (640*256) can
  2737. be represented, but if 800 dots are selected in the horizontal axis, the
  2738. window can be shifted beyond the right screen border. The same is true of
  2739. the vertical axis.
  2740.  
  2741.                                 PAGE 247
  2742.  
  2743. ----------------------------------------------------------------------------
  2744.  
  2745. 25.4.4 SMALL DRAWING PROGRAM:
  2746.  
  2747.         /* draw.c  25.4.3       */
  2748.  
  2749.         #include <exec/types.h>
  2750.         #include <intuition/intuition.h>
  2751.  
  2752.         extern LONG OpenLibrary():
  2753.         extern struct Screen *OpenScreen();
  2754.         extern struct Window *OpenWindow();
  2755.         
  2756.         struct IntuitionBase *IntuitionBase;
  2757.         struct GfxBase *GfxBase;
  2758.  
  2759.         #define INTUITION_REV 0
  2760.         #define GRAPHICS_REV 0
  2761.  
  2762.         struct TextAttr Font = 
  2763.         {
  2764.           "topaz.font",
  2765.           TOPAZ_SIXTY,
  2766.           FS_NORMAL,
  2767.           FPF_ROMFONT,
  2768.         };
  2769.  
  2770.         UBYTE screentitle[81];
  2771.  
  2772.         struct NewScreen NewScreen =
  2773.         {
  2774.            0,0,
  2775.            640,         /* Width */
  2776.            200,         /* Height - change to 256 for PAL */
  2777.            3,           /* 3 bitplanes = 8 colours      */
  2778.            2,3,         /* Another colour combination   */
  2779.            HIRES,
  2780.            CUSTOMSCREEN,
  2781.            &Font,
  2782.            screentitle,
  2783.            NULL,
  2784.            NULL,
  2785.         }:
  2786.  
  2787.         struct NewWindow NewWindow =
  2788.         {
  2789.            20,20,       /* x and y position     */
  2790.            400,180,     /* Width, height        */
  2791.            0,1,         /* Colors (0-7)         */
  2792.            CLOSEWINDOW,
  2793.            WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWSIZING |
  2794.            SIZEBRIGHT | WINDOWDRAG | WINDOWDEPTH,
  2795.            NULL,
  2796.            NULL,
  2797.            " * MY WINDOW * ",
  2798.            NULL,
  2799.            NULL,
  2800.            190,20,
  2801.            640,200,     /* IN PAL CHANGE 200 TO 256     */
  2802.            CUSTOMSCREEN
  2803.         };
  2804.  
  2805.                                 PAGE 248
  2806.  
  2807. ----------------------------------------------------------------------------
  2808.  
  2809.         main(argc,argv)
  2810.         int argc;
  2811.         char *argv[];
  2812.         {
  2813.            struct Screen *Screen;
  2814.            struct Window *Window;
  2815.            register char s[81];
  2816.            int color = 4;
  2817.            register int x,y,xalt,yalt;
  2818.  
  2819.            if((IntuitionBase = (struct IntuitionBase *)
  2820.              OpenLibrary("intuition.library",INTUITION_REV))==NULL)
  2821.                 exit(FALSE);
  2822.  
  2823.            if(argc != 4)
  2824.              {
  2825.                 printf("Error in arguments\n");
  2826.                 printf(" X-Res Y-Res Bitplanes\n");
  2827.              }
  2828.            else
  2829.              }
  2830.                 NewScreen.Width = atoi(argv[1]);
  2831.                 NewScreen.Height = atoi(argv[2]);
  2832.                 NewScreen.Depth = atoi(argv[3]);
  2833.                 if(NewScreen.Depth > 4 || NewScreen.Depth < 1)
  2834.                     NewScreen.Depth = 2;
  2835.                 color = 1 << NewScreen.Depth;
  2836.                 NewScreen.DetailPen = color - 1;
  2837.                 NewScreen.BlockPen = color - 2;
  2838.               }
  2839.  
  2840.            sprinf(screentitle,"This screen has %d colours",color);
  2841.  
  2842.            if((Screen = OpenScreen(&NewScreen))==NULL)
  2843.              exit(FALSE);
  2844.  
  2845.            NewWindow.Screen = Screen ; /* Do Not Forget This !!!!! */
  2846.  
  2847.                                 PAGE 250
  2848.  
  2849. ----------------------------------------------------------------------------
  2850.  
  2851.            if(argc == 4)
  2852.              {
  2853.                 NewWindow.Width  = Screen->Width/2;
  2854.                 NewWindow.Height = Screen->Height/3;
  2855.                 NewWindow.MinWidth = Screen->Width/3;
  2856.                 NewWindow.MinHeight = Screen->Height/5; 
  2857.                 NewWindow.Maxwidth = Screen->Width;
  2858.                 NewWindow.MaxHeigth = Screen->Height;
  2859.              }
  2860.  
  2861.            if((Window = OpenWindow(&NewWindow))==NULL)
  2862.              exit(FALSE);
  2863.  
  2864.            text(Window,"Hello There!",20,20);
  2865.         
  2866.            /* Initialise with start values */
  2867.            Move(Window->RPort, xalt = Window->MouseX,
  2868.                 yalt = Window->MouseY);
  2869.         
  2870.            /* Drawing starts here until upper or left border */
  2871.            /* is reached.                                    */
  2872.            
  2873.            while((x = Window->Mousex) > 0 && (y = Window->MouseY > 0)
  2874.              {
  2875.                 sprintf(s,"x = %3d, y = %3d",x,y);
  2876.                 text(window,s,150,7);
  2877.                 Move(Window->RPort,xalt,yalt);
  2878.                 Draw(Window->RPort,xalt = x, yalt = y);
  2879.              }
  2880.  
  2881.            text(Window,"Please click the Close Gadget ",20,20);
  2882.  
  2883.            /* wait for close gadget     */
  2884.  
  2885.            Wait(1 << Window->UserPort->mp_SigBit);
  2886.  
  2887.            CloseWindow(Window);
  2888.            CloseScreen(Screen);
  2889.            CloseLibrary(GfxBase);
  2890.            CloseLibrary(IntuitionBase);
  2891.            exit(TRUE);
  2892.         }
  2893.  
  2894.         text(w_ptr, s, x, y)
  2895.         struct Window *w_ptr;
  2896.         char *s;
  2897.         int x, y;
  2898.         {
  2899.           Move(w_ptr->RPort, x, y);
  2900.           Text(w_ptr->RPort, s , strlen(s));
  2901.         }
  2902.  
  2903.                                 PAGE 250
  2904.  
  2905. ----------------------------------------------------------------------------
  2906.  
  2907. Notice the new structure TextAttr with the variable Font. Every NewScreen
  2908. structure has, among other things, a component named Font. Here the
  2909. character set to be used can be stored (address of the structure). Of
  2910. course this is again a pointer to another structure, TextAttr.
  2911.  
  2912. The structure for the definition of a character set is very simple. First
  2913. there is the name of the font. Then the height of the character amd the
  2914. manner of presentation. Finally a flag marks the location of the character
  2915. set. We used the character set built into ROM. This font is used in the 60
  2916. character screen setting. Eighty characters can be displayed if you use
  2917. TOPAZ-EIGHTY instead of TOPAZ_SIXTY.
  2918.  
  2919. All entries of NewWindow and NewScreen are alreay initialised, but if the
  2920. user wants to use other values for resolution and bit-planes they can be
  2921. accepted. The maximum and minimum size of the windows must also be
  2922. adjusted. Since the colour indices of the window are always ready for use
  2923. with 0 and 1, no conversion has to be performed. The screen, on the other
  2924. hand, gets the last two colour registers which if course depend on the
  2925. number of colors. The program permits a maximum of 16 colours, which equals
  2926. 4 bit-planes in the high resolution mode. The title of the screen displays
  2927. this information. For this reason an additional variable must be used
  2928. because the structure has made no provisions for storing the title.
  2929.  
  2930. As soon as the window is opened the text appears. The mouse can be used to
  2931. draw something. As long as the mouse pointer doesn't move beyond the upper
  2932. or left border of the window, a line will be drawn. The mouse position is
  2933. always indicated in the title line. This is not absolute, but relative to
  2934. the upper left corner of the window. For this reason a negative value is
  2935. possible when the mouse is pushed beyond the left or upper border. The
  2936. program uses this as an end criterion.
  2937.  
  2938. Because of the output of the mouse coordinates, the current character
  2939. position in xalt and yalt must be stored in intermediate storage. Before
  2940. the drawing of the line, the values are restored again with the MOVE
  2941. function. We have said enough about this program.
  2942.  
  2943. However, we have some additional suggestions. Up to now only the define
  2944. HIRES was used for user defined screens in ViewModes, which achieves a
  2945. horizontal resolution of up to 640 pixels. The Amiga can also produce a
  2946. lower resolution which fills a complete display line with 320 pixels. With
  2947. the same number of colours only half the memory space is required. The
  2948. possibility of working with 5 bit-planes and therefore 32 colours is
  2949. created. The only thing required for this is to replace HIRES with NULL.
  2950. Try this on the first screen program. Besides the change mentioned above
  2951. only the width of the screen must be set to 320 pixels. If 5 bit-planes
  2952. were requested, 32 colour are available in colour registers 0-31.
  2953.  
  2954.                                 PAGE 251
  2955.  
  2956. ---------------------------------------------------------------------------
  2957.  
  2958.  
  2959. 25.4.5 LOW RESOLUTION AND INTERLACE MODES.
  2960.  
  2961. The interlace mode can be switched on in ViewModes. The display gets a
  2962. vertical resolution of 400 (PAL systems - 512) instead of 200 (PAL - 256)
  2963. pixels. Not bad, but here comes the big "but!". This process can only be
  2964. realised by lowering the refresh frequency of the monitor from 50 to 25 Hz.
  2965. A flickering image occurs on the Amiga monitor. This mode was only intended
  2966. for those monitors which had a long screen refresh rate and therefore don't
  2967. create flickering. Examine the display and form your own judgement. The
  2968. define LACE in the ViewModes enters interlace mode. Some Examples:
  2969.  
  2970. Low Resolution (320 pixels):
  2971.         
  2972.         NewScreen.ViewModes = NULL;
  2973.  
  2974. High Resolution (640 pixels) and interlace (400 pixels):
  2975.  
  2976.         NewScreen.ViewModes = HIRES | LACE;
  2977.  
  2978. Low Resolution (320 pixels) and interlace (400 pixels):
  2979.  
  2980.         NewScreen.ViewModes = LACE;
  2981.  
  2982. With 32 colours, a function which permits changing the colour of the pen
  2983. would be useful. This input changes the current colour in the colour
  2984. register :
  2985.  
  2986.         SetAPen(Window->RPort,color);
  2987.  
  2988. To see this routine in action, a new program must be written. Add the
  2989. following lines to the drawing program. First at the beginning of the main
  2990. function, add the definition of a variable named colour:
  2991.  
  2992.         register int, x, y, xalt, yalt, colour = 1;
  2993.  
  2994. At the end of the while loop add two additional lines. Here is the complete
  2995. loop :
  2996.  
  2997.         while((x = Window->mouseX) > 0 &&
  2998.                (y = Window->mouseY) > 0)
  2999.         {
  3000.            sprintf(s,"X = %3d, Y = %3d", x, y);
  3001.            text(Window,s,150,7);
  3002.            Move(Window->RPort,xalt,yalt);
  3003.            Draw(Window->RPort,xalt = x,yalt = y);
  3004.  
  3005.            SetAPen(Window->RPort, colour++); /* New! */
  3006.            if(colour == color) color = 1;    /* New! */
  3007.         }
  3008.  
  3009.                                 PAGE 252
  3010.  
  3011. ---------------------------------------------------------------------------
  3012.  
  3013.  
  3014. This program is on the optional disk as draw16.c. In the beginning the
  3015. variable colour is set to 1 to draw the first colour index ( 0 is the
  3016. background colour). After each small line fragment, the pen color changes
  3017. until the last index (number of colors - 1) has been reached. Then it
  3018. starts over. This produces all the colours for the first run, including the
  3019. registers not normally used. To make it even more colourful than the 16
  3020. colors in the HIRES mode, change the safety test:
  3021.         
  3022. OLD:  if(NewScreen.Depth > 4 || NewScreen.Depth < 1)
  3023.           NewScreen.Depth = 2;
  3024.  
  3025.        to
  3026.  
  3027. NEW:  if(NewScreen.Depth > 5 || NewScreen.Depth < 1)
  3028.           NewScreen.Depth = 2;
  3029.  
  3030. and change the HIRES to NULL. Consider the reduced Z resolution of 320
  3031. pixels instead of 640 pixels and change the program accordingly. This
  3032. permits drawing with 32 colours in one window. This program is on the
  3033. optional disk as draw32.c. An example call of the program for 32 colours:
  3034.  
  3035.         draw 320 200 5
  3036.  
  3037. Since many colors and high resolution requires a large amount of memory,
  3038. here are some examples of memory usage by windows and screens.
  3039.  
  3040. Low resolution, interlace mode, 32 colors:
  3041.  
  3042.         320 (pixels) * 400 (pixels) * 5 (bitplanes) / 8 (bits per byte)
  3043.         = 80,000 bytes = 78k (PAL 320*512*5/8 = 102,400)
  3044.  
  3045. High resolution, interlace mode, 8 colours:
  3046.  
  3047.         640 (pixels) * 400 (pixels) * 3 (bitplanes) / 8 (bits per byte)
  3048.         = 96,000 bytes = 93k (PAL 640*512*3/8) = 122,880)
  3049.  
  3050. Low resolution, 2 colours:
  3051.  
  3052.         320 (pixels) * 200 (pixels) * 1 (bitplanes) / 8 (bits per byte)
  3053.         = 8,000 bytes = 7.8k (PAL 320*256*1/8) = 10,240)
  3054.  
  3055.  
  3056.  
  3057. 25.4.6 PIXEL PROCESSING:
  3058.  
  3059. Other graphics commands besides Draw are :
  3060.  
  3061.         ReadPixel(Window->RPort, x, y);
  3062.         WritePixel(Window->RPort, x, y);
  3063.  
  3064.                                 PAGE 253
  3065.  
  3066. ----------------------------------------------------------------------------
  3067.  
  3068. READPIXEL :
  3069.  
  3070. READPIXEL tests whether the indicated position of a pixel is set and
  3071. returns the colour value of the pixel. If no pixel was visible, because the
  3072. pixel has the same colour as the background, ReadPixel returns a 0 to the
  3073. register number. Is the pixel is outside the window whose port is passed,
  3074. the result is -1.
  3075.  
  3076. WRITEPIXEL:
  3077.  
  3078. WRITEPIXEL sets a single pixel at the position indicated. The colour used
  3079. depends on the current colour as in all other routines and is determined
  3080. byt SetAPen.
  3081.  
  3082. The following is a program which changes the title line of the window used
  3083. in a sine format :
  3084.  
  3085.         /* pixel.c 25.4.6       */
  3086.  
  3087.         #include <exec/types.h>
  3088.         #include <intuition/intuition.h>
  3089.  
  3090.         extern struct Window *OpenWindow();
  3091.         extern long *OpenLibrary();     /* Hello Aztec User */
  3092.         extern double sin();
  3093.  
  3094.         struct IntuitionBase *IntuitionBase;
  3095.         struct GfxBase *GfxBase;
  3096.         
  3097.         #define INTUITION_REV 0
  3098.         #define GRAPHICS_REV 0
  3099.         
  3100.         /* Number of colours of workbench */
  3101.         #define WB_COLORS 4
  3102.  
  3103.         struct NewWindow NewWindow = 
  3104.         {
  3105.            10,50,       /* X and Y position */
  3106.            360,120,     /* Width, Height        */
  3107.            3,2,         /* Colour indexes       */
  3108.            NULL,
  3109.            SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH,
  3110.            NULL,
  3111.            NULL,
  3112.            "This line is Changed! ",
  3113.            NULL,
  3114.            NULL,
  3115.            0,0,
  3116.            640,200,     /* PAL users - change 200 to 256 */
  3117.            WBENCHSCREEN
  3118.         };
  3119.  
  3120.                                 PAGE 254
  3121.  
  3122. --------------------------------------------------------------------------
  3123.  
  3124.  
  3125.         main()
  3126.         {
  3127.            struct Window *Window;
  3128.            register struct RastPort *r;
  3129.            register int i, j, top, yoffset;
  3130.            int i_to, j_to, color, colors[512];
  3131.            double factor;
  3132.  
  3133.            if((IntuitionBase = (struct IntuitionBase *)
  3134.             OpenLibrary("intuition.library",INTUITION_REV))==NULL)
  3135.                exit(FALSE);
  3136.  
  3137.            if((GfxBase = (struct GfxBase *)
  3138.             OpenLibrary("graphics.library",GRAPHICS_REV))==NULL)
  3139.                exit(FALSE);
  3140.  
  3141.            if((Window = OpenWindow(&NewWindow)) == NULL)
  3142.                exit(FALSE);
  3143.  
  3144.            r = Window->RPort;
  3145.            top = Window->Height / 4 ;
  3146.            factor = 2 * 3.1415926 / Window->Width * 1.5;
  3147.             /* 1.5 sine waves */
  3148.  
  3149.            for( i = 2, i_to = Window->Width - 2; i < i_to;i++)
  3150.              {
  3151.                 for(j = 0;j < top; j++)
  3152.                   {
  3153.                     /* Transfer to Array   */
  3154.                     color = ReadPixel(r, i, j);
  3155.                     if(++color = WB_COLORS)
  3156.                       colors[j] = 0;
  3157.                     else 
  3158.                       colors[j] = color;
  3159.                       /* Increase color index by one */
  3160.                    }
  3161.                 for(j = 0, yoffset = top + top * sin(factor * i)+16;
  3162.                     j < top; j++)
  3163.                   if(colors[j]) /* if pixel should be set */
  3164.                      {
  3165.                         SetAPen(r, colors[j]);
  3166.                         WritePixel(r,i,j + yoffset);
  3167.                      }
  3168.               }
  3169.  
  3170.            Delay(1500); /* Wait 1500 ticks = 30 seconds */
  3171.            CloseWindow(Window);
  3172.            CloseLibrary(GfxBase);
  3173.            CloseLibrary(IntuitionBase);
  3174.            exit(TRUE);
  3175.         }
  3176.  
  3177.                                 PAGE 255
  3178.  
  3179. ----------------------------------------------------------------------------
  3180.  
  3181. LATTICE:
  3182.  
  3183. The library for mathematical functions and floating point numbers must be
  3184. linked with the standard library. Example :
  3185.  
  3186.         lc -lm math2
  3187.  
  3188. AZTEC:
  3189.  
  3190. If you work with the Aztec compiler, the library for mathematical functions
  3191. and floating point numbers must be linked with the standard library C.LIB. 
  3192. Example:
  3193.  
  3194.         cc +L math2.c
  3195.         ln math2.o -lm -lc
  3196.  
  3197.  
  3198. HOW THE PROGRAM WORKS :
  3199.  
  3200. The program runs under the workbench screen and it uses it's colours. Two
  3201. bit-planes (four colours) are the default. If the user constructed a
  3202. workbench screen which deviates from this, the define WB_COLORS must be
  3203. adjusted accordingly. The window which was defined in the NewWindow
  3204. structre contains only front and back gadgets. The size cannot be changed.
  3205.  
  3206. In a large loop which processes the complete width of the window, all
  3207. pixels belonging to one X position are gathered in one array. Before the
  3208. value which is returned from the ReadPixel is stored, a colour
  3209. transformation is made. Every pixel gets the colour from the following
  3210. register. The area of the display which is transmitted, is the upper
  3211. quarter of the window. To prevent mix-ups between the information to be
  3212. read and written, a complete column is first saved into the array COLORS.
  3213. Then the new position of the pixels is calculated using the SIN (sine)
  3214. function. The dots are written in the new color with WritePixel at the new
  3215. position. The pixels which are the same colour as the background are taken
  3216. out. This is tested first to increase the speed. The program will display
  3217. the top line a sine wave.
  3218.  
  3219. After complete transformation, the Delay program slightly delays the end of
  3220. the program to give the user to opportunity to view the window again. The
  3221. parameter provides the waiting time in 1/50 second ticks. To achieve a
  3222. delay of 30 seconds 1500 ticks must be stored.
  3223.  
  3224.                                 PAGE 256
  3225.  
  3226. ---------------------------------------------------------------------------
  3227.  
  3228.  
  3229. 25.5 DOS
  3230.  
  3231. Besides intuition, DOS (the Disk Operating System) is usually required when
  3232. programming. Many programs wouldn't work without the help of AmigaDos. The
  3233. DOS routines handle file deletion and renaming, as well as directory
  3234. creation and directory display.
  3235.  
  3236. DOS is also stored in a library file (dos.library). Unlike the other
  3237. libraries dos.library is always open to the user. It doesn't have to be
  3238. opened or closed by the user. It is as simple to use as the functions from
  3239. the standard library. For example, deleting a file:
  3240.  
  3241.         result = DeleteFile(filename);
  3242.  
  3243. The return value is an integer number which indicates an error if zero and
  3244. the correct processing with a number unequal to zero. Complete directories
  3245. can be deleted with this function. No files may be contained in the
  3246. directory. They must be erased in advanced. The RENAME function is just as
  3247. easy to use for renaming files:
  3248.  
  3249.         result = Rename(old_name, new_name);
  3250.  
  3251. The result is also a value unequal to zero. The other parameters old_name
  3252. and new_name are just like the filename strings which contain a valid
  3253. filename.
  3254.  
  3255.                                 PAGE 257
  3256.  
  3257. ----------------------------------------------------------------------------
  3258.  
  3259. 25.6 SETCOMMENT.
  3260.  
  3261. One routine permits the attachment of a comment to a file. This comment is
  3262. completely independant of the content and size of the file and is stored in
  3263. the same place as the filename and it's parameters. The DOS command
  3264. FILENOTE in the C: directory can attach a comment text to an existing file.
  3265. This can also be done with the function:
  3266.  
  3267.         result = SetComment(filename, comment);
  3268.  
  3269. A short program shows this routine in action:
  3270.  
  3271.         /* Makecom.c 25.6       */
  3272.  
  3273.         #include <libraries/dos.h>
  3274.  
  3275.         main(argc,argv)
  3276.         int argc;
  3277.         char *argv[];
  3278.         {
  3279.            if(argc == 3)
  3280.              {
  3281.                if(!SetComment(argv[1], argv[2]))
  3282.                 printf("Error %d\n",IoErr());
  3283.              }
  3284.            else
  3285.              {
  3286.                printf("Format : MAKECOM FILE COMMENT \n");
  3287.  
  3288.         exit(TRUE);
  3289.  
  3290.         }
  3291.  
  3292. The filename and the comment passes to the program through the command
  3293. line. As in all data transfers, the use of spaces in the actual comment is
  3294. not permitted. Here is a sample call:
  3295.  
  3296. 'makecom makecom.c This-is-a-comment-use-the-list-command-to-display-it'
  3297.  
  3298.                                 PAGE 258
  3299.  
  3300. ----------------------------------------------------------------------------
  3301.  
  3302. 25.7 READ DIRECTORY:
  3303.  
  3304. Many programs that handle files should have a routine for reading disk
  3305. directories. To make this possible in a program various functions are
  3306. required.
  3307.  
  3308. First there is the LOCK function. LOCK locks the specified directory for
  3309. access. Only after the LOCK can other functions operate on the directory.
  3310. The name of the directory and the access mode are passed to LOCK. Finally
  3311. an integer value for READ is passed with the define ACCESS_READ. The
  3312. returned key permits the processing of this one directory, similar to a
  3313. handle for file accesses or a window pointer under intuition. If this key
  3314. is equal to zero an error has occurred.
  3315.  
  3316. Two functions are required for reading a directory. One is EXAMINE, the
  3317. other EXNEXT. First EXAMINE must be called to obtain the first entry of the
  3318. directory. Then a call for EXNEXT must follow for each additional file or
  3319. directory. Both routines require both LOCK and a pointer to the
  3320. FILEINFOBLOCK structure. This structure contains all important file data.
  3321.  
  3322.         result = Examine(lock, &fileinfo);
  3323.  
  3324. And here is the structure definition:
  3325.  
  3326.         struct FileInfoBlock {
  3327.         LONG fib_DiskKey;
  3328.         LONG fib_DirEntryType;
  3329.         char fib_FileName[108];
  3330.         LONG fib_Protection;
  3331.         LONG fib_EntryType;
  3332.         LONG fib_Size;
  3333.         LONG fib_NumBlocks;
  3334.         struct DateStamp fib_Date;
  3335.         char fib_Comment[116];
  3336.         }
  3337.  
  3338. The fib_DirEntryType function indicates whether the data currently read is
  3339. a normal file (<0) or a directory (>0).
  3340.  
  3341. The fib_FileName function contains the name which can be up to 30
  3342. characters long, even though it was generously defined here a 108
  3343. characters.
  3344.  
  3345. The fib_Protection function contains flags which indicate whether the file
  3346. can be read, written , executed or erased. The variable is defined as LONG
  3347. (32 bits) but only the lower 4 bits are required.
  3348.  
  3349.                                 PAGE 259
  3350.  
  3351. ----------------------------------------------------------------------------
  3352.  
  3353.  
  3354. The priorities for these files are as follows:
  3355.  
  3356.         R           W           E           D
  3357.         8           4           2           1
  3358.       R=Read      W = Write   E = Execute  D = Delete
  3359.  
  3360. For every protection action one of the above bits must be set. For example
  3361. if a file or directory can only be read or erased, the flags W and E must
  3362. be set:
  3363.  
  3364.         RWED
  3365.         0110 (bits) = 4 + 2 = 6
  3366.  
  3367. This variable must contain the value 6. It is important to set the flag
  3368. whose function is forbidden. To make changes please use the PROTECT command
  3369. from the CLI. The flags which are passed with this program are changed in
  3370. such a manner that the functions can be performed. This is exactly the
  3371. opposite of their use in the user program. To protect a file from erasing
  3372. the following line is required:
  3373.  
  3374.         PROTECT ED RWE
  3375.  
  3376. The fib_Size function defines the file size in bytes.
  3377.  
  3378. The fib_NumBlocks function contains the number of occupied blocks on the
  3379. disk.
  3380.  
  3381. The fib_Date function contains the data when the file was last written.
  3382.  
  3383. The fib_Comment function contains the comments for the file.
  3384.  
  3385. You now have all the information needed to construct the final program. For
  3386. the sake of simplicity we use parameter passing with the command line in
  3387. the version. The parameter indicates the directory which should be read.
  3388.  
  3389.  
  3390.                                 PAGE 260
  3391.  
  3392. ----------------------------------------------------------------------------
  3393.  
  3394.         /* Read_dir.c   25.7    */
  3395.  
  3396.         #include <libraries/dos.h>
  3397.  
  3398.         struct FileInfoBlock fi;
  3399.  
  3400.         main(argc,argv) 
  3401.         int argc;
  3402.         char *argv[];
  3403.         {
  3404.            long lock;
  3405.            int error;
  3406.            char filepath[100];
  3407.  
  3408.            if(argc == 2) /* Parameter Present ? */
  3409.              strcpy(filepath, argv[1]);
  3410.            else
  3411.              strcpy(filepath,"sys:");
  3412.  
  3413.            lock = Lock(filepath,ACCESS_READ);
  3414.            printf("Lock value %d\n", lock);
  3415.            if(!lock)
  3416.              {
  3417.                 printf("No Lock! ERROR!\n");
  3418.                 exit(FALSE);
  3419.              }
  3420.  
  3421.            if(Examine(lock,&fi)) /* First call successful ? */
  3422.              do
  3423.                 output();       /* return value not of interest now */
  3424.              while(ExNext(lock,&fi)); /* Until error occurs */
  3425.  
  3426.            error = IoErr(); /* What error ? */
  3427.            if(error!= ERROR_NO_MORE_ENTRIES) /* "real" error */
  3428.               printf("Error %d occured!\n",error);
  3429.  
  3430.            exit(TRUE);
  3431.         }
  3432.  
  3433.         output()
  3434.         {
  3435.            if(!*fi.fib_FileName)        /* strlen = 0 */
  3436.              {
  3437.                 printf("Empty!\n");
  3438.                   /* for example root-directory of RAM disk */
  3439.                   return(0);    /* That's directory without name */
  3440.              }
  3441.  
  3442.            if(fi.fib_DirEntryType > 0)
  3443.               printf("Directory Name");
  3444.            else
  3445.               printf("Filename      ");
  3446.  
  3447.            printf(": >%20s< RWXD %lx bytes: %-6ld Block %-4ld\n",
  3448.                    fi.fib_Filename, fi.fib_Protection,
  3449.                    fi.fib_Size, fi.fib_NumBlocks);
  3450.  
  3451.            if(*fi.fib_Comment)  /* if comment present output it ! */
  3452.              printf("Comment: >%s< \n", fi.fib_Comment);
  3453.            return(fi.fib_DirEntryType > 0); /* Return file type */
  3454.         }
  3455.  
  3456. The protection flags are not decoded separately in this program (it wouldnt
  3457. be a problem to do that), but are presented as a hexadecimal number (the
  3458. %lx format instruction). You can enhance this program if you wish.
  3459.  
  3460. The flags can be displayed in RWED format using the LISt command from the
  3461. CLI. With PROTECT any flag can be set and with list the result can be
  3462. observed. This information can be compared with the results from the user
  3463. program.
  3464.  
  3465.                                 PAGE 261
  3466.  
  3467. ----------------------------------------------------------------------------
  3468.  
  3469. 25.8 CONCLUSION.
  3470.  
  3471. You now have the general knowledge needed to write simple programs in the C
  3472. language. As you take time to develop your own programs, functions and
  3473. libraries, keep this book nearby for reference. Since it's difficult to
  3474. memorize everything about a language, this book will help you with the
  3475. complex concepts of the C language.
  3476.  
  3477. You may be wondering why we didn't spend more time with the aspects of the
  3478. Amiga. We admit that we didn't include as much about the operating system
  3479. and Intuition as we would have liked. However, these are difficult concepts
  3480. for a beginner to understand, and we felt it best to just give the reader a
  3481. few general examples controlling these areas in C. Since C is a
  3482. transportable language, you may prefer to write transportable source codes.
  3483.  
  3484. If you want to continue your education in C, we recommend the Abacus book
  3485. AMIGA C FOR ADVANCED PROGRAMMERS (*-*-*** LOOK OUT FOR THIS TITLE ON FUTURE
  3486. ALLIANCE DOX DISKS - RAZOR BLADE *-*-***). This book coovers subjects that
  3487. interest professional Amiga programmers: Combining assembly language and
  3488. source codes; debugging (finding errors); jump table and more. In addition,
  3489. AMIGA C for advanced programmers details Intuition programming in C (menus
  3490. , requesters etc..)
  3491.  
  3492. We wish you luck in your future as a C programmer.
  3493.  
  3494.                 *-*-*-* Alliance *-*-*-*
  3495.  
  3496.                                 PAGE 262
  3497.  
  3498. -----------------------------------------------------------------------------
  3499.  
  3500.                         APPENDICES
  3501.  
  3502. APPENDIX A - FUNCTIONS.
  3503.  
  3504. /*                                                                       */
  3505. /* NAME : STRLEN                                                         */
  3506. /* PARAMETER: S (STRING)                                                 */
  3507. /* RETURN VALUE: LENGTH (INT)                                            */
  3508. /* FUNCTION: RETURN NUMBER OF CHARACTERS IN "S"                          */
  3509. /* OTHER:                                                                */
  3510.  
  3511. strlen(s)
  3512. char s[];
  3513. {
  3514.    register int i = 0;
  3515.    while(s[i])
  3516.      i++;
  3517.    return(i)
  3518. }
  3519.  
  3520.  
  3521.  
  3522. /*                                                                      */
  3523. /* Name :  strcpy                                                       */
  3524. /* Parameter: s (string) , t (string)                                   */
  3525. /* return value: -                                                      */
  3526. /* Function: Copies "s" to "t"                                          */
  3527. /* Other:                                                               */
  3528.  
  3529. strcpy(t,s)
  3530. register char *t, *s;
  3531. {
  3532.         while(*t++ = *s++)
  3533.           ;
  3534. }
  3535.  
  3536.  
  3537.  
  3538. /*                                                                      */
  3539. /* Name: strcat                                                         */
  3540. /* Parameter: s (string) , t (string)                                   */
  3541. /* Return Value : -                                                     */
  3542. /* Function: attach "t" to "s"                                          */
  3543. /* Other:                                                               */
  3544.  
  3545. strcat(s,t)
  3546. register char *s, *t;
  3547. {
  3548.         while(*s)
  3549.           s++;
  3550.         while(*s++ = *t++);
  3551. }
  3552.  
  3553.                                 PAGE 265
  3554.  
  3555. ----------------------------------------------------------------------------
  3556.  
  3557. /*                                                                      */
  3558. /* Name: letter                                                         */
  3559. /* Parameter: z (char)                                                  */
  3560. /* Return value: If a letter (1) else (0)                               */
  3561. /* Function: Determine if it was a letter or not.                       */
  3562. /* Other: -                                                             */
  3563.  
  3564. #define FALSE 0
  3565. #define TRUE 1
  3566.  
  3567. letter(z)
  3568. register char z;
  3569. {
  3570.         if((z>='a' && z <='z') || (z >='A' && z <='Z'))
  3571.           return(TRUE);
  3572.         return(FALSE);
  3573. }
  3574.  
  3575.  
  3576. /*                                                                      */
  3577. /* Name: c_comp                                                         */
  3578. /* Parameter: c1 (char) , c2 (char)                                     */
  3579. /* REturn Value: 1 (TRUE), 0 (FALSE)                                    */
  3580. /* Function: Compares two characters.                                   */
  3581. /* Other : requires two characters ()                                   */
  3582.  
  3583. #define FALSE 0
  3584. #define TRUE 1
  3585. extern int grklflag;
  3586.  
  3587. c_comp(c1,c2)
  3588. register char c1,c2;
  3589. {
  3590.         if (c1 == c2) return(TRUE);
  3591.         if(grklflag && letter(c1) && letter(c2))
  3592.            if((c1 + 'a' - 'A' == c2) || (c2 + 'a' - 'A' = c1))
  3593.               return(TRUE);
  3594.         return(FALSE);
  3595. }
  3596.  
  3597.  
  3598.                                 PAGE 266
  3599.  
  3600. ----------------------------------------------------------------------------
  3601.  
  3602. /*                                                                      */
  3603. /* Name: strcmp                                                         */
  3604. /* Parameter: s (string) , t (string)                                   */
  3605. /* Return Value: identical 0 not identical 1                            */
  3606. /* Function: Compares "s" and "t"                                       */
  3607. /* Other:  -                                                            */
  3608.  
  3609. strcmp(s,t)
  3610. register char *s, *t;
  3611. {
  3612.         register int identical;
  3613.         while(identical = c_comp(*s,*t++))
  3614.            if(!*s++)
  3615.              return(0);
  3616.         return(!identical);
  3617. }
  3618.  
  3619.  
  3620. /*                                                                      */
  3621. /* Name: strchar                                                        */
  3622. /* Parameter: s (string). c (char)                                      */
  3623. /* Return Value: Position (int) or -1                                   */
  3624. /* Function: Determines position of char "c" in "s"                     */
  3625. /* Other:   -                                                           */
  3626.  
  3627. strchar(s,c)
  3628. register char s[];
  3629. register char c;
  3630. {
  3631.         register int i = 0;
  3632.         while(!c_comp(s[i],c) && s[i])
  3633.            i++;
  3634.         if(s[i]) return(i);
  3635.         return(-1);
  3636. }
  3637.  
  3638.  
  3639. /*                                                                      */
  3640. /* Name: strchback                                                      */
  3641. /* Parameter: s (string) , c (char)                                     */
  3642. /* Return Value: Index (int)                                            */
  3643. /* Function: Searches for Position of char "c" in "s"                   */
  3644. /* Other: requires c_comp(), strlen()                                   */
  3645.  
  3646. strchback(s,c)
  3647. register char s[];
  3648. register char c;
  3649. {
  3650.         register int i = strlen(s);
  3651.         while((i >= 0) && !c_comp(s[i],c))
  3652.           i--;
  3653.         return(i);  /* Error = -1 */
  3654. }
  3655.  
  3656.                                 PAGE 267
  3657.  
  3658. ----------------------------------------------------------------------------
  3659.  
  3660. /*                                                                      */
  3661. /* Name: ltoa                                                           */
  3662. /* Parameter: n (long), s (string)                                      */
  3663. /* Return Value -                                                       */
  3664. /* Function: Converts long value to a char string                       */
  3665. /* Other: Requires reverse.                                             */
  3666.  
  3667.  
  3668. #define TRUE 1
  3669. #define EOS '\0'
  3670.  
  3671. itoa(n, s)
  3672. register char s[];
  3673. register long n;
  3674. {
  3675.         register int i = 0;
  3676.         register int forechar = 0;
  3677.         if(n<0)
  3678.           {
  3679.              forechar = TRUE;
  3680.              n = -n;
  3681.           }
  3682.         do
  3683.           {
  3684.              s[i++] = n % 10 + '0';
  3685.           } while((n /= 10) > 0);
  3686.  
  3687.         if(forechar)
  3688.           s[i++] = '-';
  3689.         s[i] = EOS
  3690.         reverse(s);
  3691. }
  3692.  
  3693.  
  3694. /*                                                                      */
  3695. /* Name: itoa                                                           */
  3696. /* Parameter: n (int), s (string)                                       */
  3697. /* Return value: -                                                      */
  3698. /* Function: Converts integer string to char value.                     */
  3699. /* Other: requires ltoa()                                               */
  3700.  
  3701. itoa(n, s)
  3702. register int n;
  3703. register char s[];
  3704. {
  3705.         ltoa((long) (n),s);
  3706. }
  3707.  
  3708.                                 PAGE 268
  3709.  
  3710. ----------------------------------------------------------------------------
  3711.  
  3712.  
  3713. /*                                                                      */
  3714. /* Name: atol                                                           */
  3715. /* Parameter: s (string)                                                */
  3716. /* Return Value: n (long)                                               */
  3717. /* Function: Converts char string into long value.                      */
  3718. /* Other:                                                               */
  3719.  
  3720. long atol(s)
  3721. register char *s;
  3722. {
  3723.         register long val;
  3724.         register int sign = 1;
  3725.         while(*s == ' ')
  3726.            s++;
  3727.         if(*s== '+' || *s == '-')
  3728.            sign = (*s++ == '+') ? 1 : -1;
  3729.         for(val = 0; *s >= '0' && *s <= '9'; ++s)
  3730.            val = 10 * val + *s - '0';
  3731.         return(sign * val);
  3732. }
  3733.  
  3734.  
  3735. /*                                                                      */
  3736. /* Name: atoi                                                           */
  3737. /* Parameter: s (string)                                                */
  3738. /* Return Value: Integer number                                         */
  3739. /* Function: Converts char string into Integer.                         */
  3740. /* Other: Requires atol.                                                */
  3741.  
  3742. atoi(s)
  3743. register char *s;
  3744. {
  3745.         long atol();
  3746.         return(atol(s));
  3747. }
  3748.  
  3749.                                 PAGE 269
  3750.  
  3751. -----------------------------------------------------------------------------
  3752.  
  3753.                      APPENDIX B - THE HISTORY OF C.
  3754.  
  3755. C originated from BCPL (Basic Cambridge Programming Language). The B
  3756. language came from BCPL and C came from the B language. C was developed in
  3757. the mud-seventies by Dennis M Ritchie, who, at that time, was working for
  3758. Bell laboratories.
  3759.  
  3760. C was originally intended for developing an operating system which, among
  3761. other things, would be capable of multi-user and multitasking execution,
  3762. namely UNIX. This explains why C programs are so fast. Multitasking
  3763. procedures require a very fast operating system which up to then could only
  3764. be written in assembly language. Dennis Ritchie developed the C language to
  3765. circumvent the error prone and unclear assembly language programming. The
  3766. result, the UNIX operating system, consists of about 13,000 lines of which
  3767. only a minimum of about 800 lines were written in assembly language. The
  3768. rest of the operating system is in C.
  3769.  
  3770. C became popular with the introduction of the Amiga and the Atari ST, whose
  3771. operating systems were written in C. The Amiga's intuition user interface
  3772. was written almost completely in C. Professional programmers and software
  3773. houses prefer using C to develop new programming projects. C has another
  3774. advantage: it is portable. This means that C programs can, theoretically,
  3775. be transferred to other computers and compiled there without changes.
  3776.  
  3777. The reason for this is that C has a small number of commands available to
  3778. all compilers. Parts which are computer specific such as input and output
  3779. don't belong to the actual C language. These routines are delivered with
  3780. the language in libraries adapted to the peculiarities of that particular
  3781. computer. The C programmer doesn't have to be concerned about this. He
  3782. knows that the GETCHAR function gets a character from the keyboard
  3783. regardless of whether the progran is executing on a C64, an IBM PC, an
  3784. Amiga or an Atari ST. This portability means less programming for the
  3785. developers - just transfer the program over to another computer, make the
  3786. changes needed for the new computer and recompile it.
  3787.  
  3788. HOW A C COMPILER WORKS:
  3789.  
  3790. Every C compiler has been split into various program portions which,
  3791. depending on the manufacturer, are available either in a program module or
  3792. in several smaller programs.
  3793.  
  3794. The first part of a C compiler is the preprocessor; this only replaces one
  3795. text portion with another according to the user's commands. The result of
  3796. this effort is a file containing pure text which can be processed with the
  3797. editor. The result passses to the scanner which searches for command words
  3798. specific to C. It recognises these words and stored them in abbreviated
  3799. form. In this format the command is stored as a token (code) instead of as
  3800. individual letters. Tokenizing takes up less memory and accelerates the
  3801. translation.
  3802.  
  3803.                                 PAGE 270
  3804.  
  3805. ----------------------------------------------------------------------------
  3806.  
  3807. PARSER:
  3808.  
  3809. After completeing this test run, the parser appears. If tests the source
  3810. code commands for the correct syntax, and differentiates between correct
  3811. and incorrect combinations of C commands. The parser knows all the rules
  3812. about C syntax. Just as in everyday conversation, string words together
  3813. isn't enough. The parser ensures that the expression is correct.
  3814.  
  3815. As the lasst part of the actual C compiler, the code generator converts the
  3816. text processed by the parser into machine language commands. Some C
  3817. compilers first translate the machine language commands into assembly
  3818. language so the programmer can streamline the generated code. This is
  3819. really unnecessary since the C compilers on the market already produce very
  3820. efficient machine language code. After completing this run, the compiler
  3821. saves the object code to disk with the extension of .o.
  3822.  
  3823. The final process is linking the object files with the required libraries
  3824. to produce an executable program. The linker is used for this purpose.
  3825.  
  3826.  
  3827.                                 PAGE 271
  3828.  
  3829. ----------------------------------------------------------------------------
  3830.  
  3831.  
  3832.                     APPENDIX C - THE LATTICE C COMPILER.
  3833.  
  3834. C compiler manufacturers are constantly updating and improving their
  3835. compilers. For instruction on how to install the compiler, see the
  3836. documentation and any README files that came with the compiler.
  3837.  
  3838. The C compiler is called with lc and the source filename. As a minimum the
  3839. following is required:
  3840.  
  3841.         lc hello
  3842.  
  3843. With the -L option, the linker can be loaded immediately after the call of
  3844. the C compiler. The linke (here BLINK) can also be called independantly.
  3845. This is a standard call to compile and link a source code named math2.c
  3846. into a program named math2.
  3847.  
  3848. When the library for mathematical functions and floating point numbers must
  3849. be linked with the standard library, the following can be used:
  3850.  
  3851.         lc -Lm math2
  3852.  
  3853. THE LINKER:
  3854.  
  3855. The program BLINK provides a powerful linker for the programmer. Here are
  3856. the most important options available in this linker
  3857.  
  3858. After the name BLINK all files which are linked together appear after the
  3859. FROM argument (or ROOT, or even nothing). The name of the program to be
  3860. executed follows the TO argument. Library files to be searched are listed
  3861. after the LIBRARY argument. Some sample calls:
  3862.  
  3863.         BLINK FROM a, b, c TO program
  3864.  
  3865.         BLINK a+b+c TO program LIBRARY folder/d
  3866.  
  3867.         BLINK ROOT a,b,c TO folder/prg LIBRARY system/lib, obj/special
  3868.  
  3869. Using the parameter WITH all options can be stored in a file just as in a
  3870. MAKE file. A linker call is then:
  3871.  
  3872.         BLINK WITH file
  3873.  
  3874. In the FILE the options mentioned above contain a parameter in each new
  3875. line. For Example:
  3876.  
  3877.         ROOT a,b,c
  3878.         TO folder/prg
  3879.         LIBRARY system/lib, obj/special
  3880.  
  3881.  
  3882.                                 PAGE 272
  3883.  
  3884. ----------------------------------------------------------------------------
  3885.  
  3886.                      APPENDIX D - THE AZTEC C COMPILER
  3887.  
  3888.  
  3889. C compiler manufacturers are constantly updating and improving their
  3890. compilers. For instruction on how to install the compiler, see the
  3891. documentation and any README files that came with the compiler.
  3892.  
  3893. The compiler with the name CC can be found in directory C. The call is very
  3894. simple:
  3895.  
  3896.         cc file.c
  3897.  
  3898. The source file file.c is compiled and translated into asssembly code. This
  3899. code can be optimised by a machine language programmer. This file has the
  3900. name ctmpaxx.xxx where x is a number which differs from one call to the
  3901. next. It is best to look at the current directory because this name is
  3902. needed imnmediately.
  3903.  
  3904. Also Aztec uses symbolic names for devices which are listed as follows:
  3905.  
  3906.         CLIB
  3907.         INCLUDE
  3908.         CCTEMP
  3909.  
  3910. CCTEMP determines where temporary files created by the C compiler will be
  3911. stored. CLIB indicates the path to the libraries, while INCLUDE is the path
  3912. for the header (.h) files. Examples are:
  3913.  
  3914.         assign CLIB: df0:lib/
  3915.         assign INCLUDE: df0:include/
  3916.         assign CCTEMP: ram:
  3917.  
  3918. Various options can be placed in front of the name of the file to be
  3919. compiled. Here are the most important:
  3920.  
  3921. -Ipath:
  3922.  
  3923. With -I a pathname can be provided in which the Include files are assumed
  3924. to be. The search for these files is made only in the sub-directory. The
  3925. option is comparable with the assignment INCLUDE (see above).
  3926.  
  3927. NOTE: The pathname immediately follows the I without any additional spaces.
  3928. For example:
  3929.  
  3930.         cc -Iram:includes/privat/
  3931.  
  3932.                                 PAGE 273
  3933.  
  3934. ----------------------------------------------------------------------------
  3935.  
  3936. +C
  3937.  
  3938. Creates longer code, since jumps within the program code are equipped with
  3939. 32-bit commands instead of 16-bit commands which could have been used.
  3940.  
  3941. +D
  3942.  
  3943. Causes data to be stored in 32-bit format. This slows down data access and
  3944. increases memory requirements, but makes data segments of any desired
  3945. possible size (theoretically). During a "normal" data access with 16-bit
  3946. addressing , the user is limited to a maximum of 64k of data.
  3947.  
  3948. +L
  3949.  
  3950. Variables and constants of INT type are stored in 32-bit format. Because of
  3951. this the programs become (partially) Lattice compatible since this compiler
  3952. always uses 32 bits. Without this option 16 bits are sufficient for INT
  3953. numbers.
  3954.  
  3955. -D 
  3956.  
  3957. Defines a constant. It corresponds to the define statement, but is
  3958. assigned during the call of the compiler. No space can follow this option
  3959. character. Example:
  3960.  
  3961.         cc -DTESTRUN=1 file.c
  3962.  
  3963. The assignment corresponds to the define 
  3964.  
  3965.         #define TESTRUN 1
  3966.  
  3967. -S 
  3968.  
  3969. Suppresses warnings. The warnings are only messages and the compiled
  3970. programs are usually capable of being run. To identify the real errors,
  3971. this option can be used to display only the error messages on the monitor.
  3972.  
  3973. +P
  3974.  
  3975. Causes the compiler to create Lattice compatible code. All data jumps and
  3976. INT numbers are automatically created in the 32-bit version.
  3977.  
  3978.  
  3979. THE ASSEMBLER:
  3980.  
  3981. After the C compiler comes the assembler which is named AS. It is also
  3982. stored in the C: directory. The call is similar to the C compiler.
  3983.  
  3984.         as file.o
  3985.  
  3986. With the option -O a new name can be given to the new file. Example:
  3987.  
  3988.         as -O program.o ctmpxyz.123
  3989.  
  3990. Additional options are only of interest to the assembler specialist. Since
  3991. this book deals with C programming, they will not be considered further. It
  3992. is only an intermediate step.
  3993.  
  3994. THE LINKER:
  3995.  
  3996. For Aztec the linker provided is called LN and can be found in the C:
  3997. sub-directory. The files to be linked together are placed one behind the
  3998. other. Whether they are libraries or modules doesn't matter in principle,
  3999. but libraries should be placed at the end of the list.
  4000.  
  4001.                                 PAGE 274
  4002.  
  4003. ----------------------------------------------------------------------------
  4004.  
  4005.         ln file.o c.lib
  4006.  
  4007. The standard file c.lib is also like other libraries in the lib: directory.
  4008. Several modules can be linked together:
  4009.  
  4010.         ln -o result modul1.o modul2.o modul3.o c.lib
  4011.  
  4012. The name assignment for the resulting program is performed with -O. The
  4013. linker can be informed about libraries with -L, but the extension of .lib
  4014. is then omitted. Example:
  4015.  
  4016.         ln file.o -Lc -Lm
  4017.  
  4018. Two additional options are +C and +F which permit selection of special
  4019. storage areas. A code letter follows the option which has the following
  4020. significance:
  4021.  
  4022.         c       program
  4023.         d       initialised data
  4024.         b       data which was not initialised.
  4025.  
  4026. The +C stands for standard chip memory, +F for fast memory. These two
  4027. groups of RAM areas are especially important for graphic programming since
  4028. certain data must always be stored in chip memory. With this option the
  4029. following can be requested:
  4030.  
  4031.         ln +Cdb +Fc file.o -Lc
  4032.  
  4033. This causes the storage of data in chip-memory and the storage of the
  4034. program in the normal fast memory. Without a special statement, all
  4035. information would have been stored in the fast memory area.
  4036.  
  4037. Here is a MAKE file which is tailored to Aztec C:
  4038.  
  4039.         .key file
  4040.  
  4041.         echo "Compiling  <file$t1>.c "
  4042.         cc -t <file$t1>.c
  4043.         echo "Assembling <file$t1>.asm "
  4044.         as <file$t1>.asm
  4045.         echo "Linking <file$t1>.ams to <file$t1>  "
  4046.         ln <file$t1>.o -lm -lc
  4047.         ; -lm -lc is called :link clib and mathlib in addition.
  4048.         echo "Everything clear !"
  4049.         
  4050. The file is named az-make on the optional program disk. Here is an example
  4051. call to compile, assemble and link a source file named array.c:
  4052.  
  4053.         execute az-make array
  4054.  
  4055.                                 PAGE 275
  4056.  
  4057. ----------------------------------------------------------------------------
  4058.  
  4059.                     APPENDIX E - COMPILER RESERVED WORDS
  4060.  
  4061. Commands which are presented here, but were not described in the book,
  4062. either have no function in the current C compilers, or are reserved for
  4063. future version.
  4064.  
  4065.         auto            enum            short
  4066.  
  4067.         break           extern          sizeof  
  4068.  
  4069.         case            float           static
  4070.         
  4071.         char            for             struct
  4072.  
  4073.         continue        goto            switch
  4074.  
  4075.         default         if              typedef
  4076.  
  4077.         do              int             union
  4078.                 
  4079.         double          long            unsigned
  4080.  
  4081.         else            register        void
  4082.  
  4083.         entry           return          while
  4084.  
  4085.  
  4086.  
  4087.  
  4088.                                 PAGE 276
  4089.  
  4090. ----------------------------------------------------------------------------
  4091.  
  4092.  
  4093.                      APPENDIX F - OPERATOR PRECEDENCE.
  4094.  
  4095. Precedence      Operator        Description                  Evalution.
  4096. ----------      --------        ---------------------------  ---------
  4097.  
  4098. 1               ()              function                     left to right
  4099.                 []              array                        left to right
  4100.                 .               structure declaration        left to right
  4101.                 ->              structure declaration        left to right
  4102. 2               cast            Forced type conversion       right to left.
  4103.                 *               content of                   right to left.
  4104.                 &               address of                   right to left.
  4105.                 -               Negative sign                right to left.
  4106.                 !               logical NOT                  right to left.
  4107.                 ~               Bitwise complement.          right to left.
  4108.                 ++              Increment.                   right to left.
  4109.                 --              Decrement.                   right to left.
  4110.                 sizeof          storage requirement          right to left.
  4111. 3               *               multiplication               left to right
  4112.                 /               division                        "     "
  4113.                 %               remainder (modulo)              "     "
  4114. 4               +               addition                        "     "
  4115.                 -               subtraction                     "     "
  4116. 5               >               shift to right                  "     "
  4117.                 <               shift to left                   "     "
  4118. 6               <               less than                       "     "
  4119.                 >               greater than                    "     "
  4120.                 <=              Less than or equal to           "     "
  4121.                 >=              Greater than or equal to        "     "
  4122. 7               ==              equal                           "     "
  4123.                 !=              unequal                         "     "
  4124. 8               &               bitwise AND                     "     "
  4125. 9               ^               bitwise EXOR                    "     "
  4126. 10              |               bitwise OR                      "     "
  4127. 11              &&              Logical AND                     "     "
  4128. 12              ||              Logical OR                      "     "
  4129. 13              ?:              Conditional evaluation.      right to left
  4130. 14              =               Assignment.                     "      "
  4131.                 #=              abbreviated assignment          "      "
  4132. 15              ,               Separation of expressions    left to right.
  4133.  
  4134.  
  4135.                                 PAGE 277
  4136.  
  4137. ----------------------------------------------------------------------------
  4138.  
  4139.                           APPENDIX G - STORAGE CLASSES
  4140.  
  4141. STORAGE CLASS           VALIDITY                DURATION.
  4142. -------------           ----------              ----------
  4143.  
  4144. auto                    Block                   Block.
  4145. extern                  Program                 Program.        
  4146. register                Block                   Block
  4147. static (intern)         Block                   Program
  4148. static (extern)         Block                   Program
  4149.  
  4150.  
  4151.  
  4152.                           APPENDIX H - TYPE CONVERSIONS.
  4153.  
  4154.  
  4155. Rules:
  4156.  
  4157. 1.) CHAR and SHORT are always converted to INT and FLOAT into DOUBLE.
  4158.  
  4159. 2.) If after this conversion one of the operators should have the type
  4160. DOUBLE, the second operand and the result are also converted to double.
  4161.  
  4162. 3.) If a data type is LONG, all participating values are also transformed
  4163. to LONG.
  4164.  
  4165. 4.) If an UNSIGNED value is found among the operands, all values are
  4166. converted to UNSIGNED.
  4167.  
  4168.                                 PAGE 278
  4169.  
  4170. ----------------------------------------------------------------------------
  4171.  
  4172.                         APPENDIX I - MODES FOR FOPEN.
  4173.  
  4174. LATTICE C:
  4175.  
  4176. String          Create  Cut File   Read   Write    Append    Binary
  4177. -------------------------------------------------------------------
  4178. "r"             no      no         yes    no       no        yes
  4179. "w"             yes     yes        no     yes      no        yes
  4180. "a"             yes     no         no     no       yes       yes
  4181. "r+"            no      no         yes    yes      no        yes
  4182. "w+"            yes     no         yes    yes      no        yes
  4183. "a+"            yes     no         yes    no       yes       yes
  4184. "ra"            no      no         yes    no       no        no 
  4185. "wa"            yes     yes        no     yes      no        no
  4186. "aa"            yes     no         no     no       yes       no
  4187. "ra+"           no      no         yes    yes      no        no 
  4188. "wa+"           yes     no         yes    yes      no        no
  4189. "aa+"           yes     no         yes    no       yes       no
  4190. "rb"            no      no         yes    no       no        yes
  4191. "wb"            yes     yes        no     yes      no        yes
  4192. "ab"            yes     no         no     no       yes       yes
  4193. "rb+"           no      no         yes    yes      no        yes
  4194. "wb+"           yes     no         yes    yes      no        yes
  4195. "ab+"           yes     no         yes    no       yes       yes
  4196.  
  4197. No conversions are made for binary files. If the file was opened as an
  4198. ASCII file, which can be recognised by the "a" at the second place, all
  4199. carriage returns (code 13=\r) are eliminated and the character with the
  4200. ASCII code 26 is converted to EOF (-1) during reading. During writing, the
  4201. single line feed (\n), is converted to the character combination \r\n.
  4202.  
  4203. To differentiate the two modes, Lattice C uses an internal INT variable
  4204. named _fmode. If the highest value is set (_fmode & 0x8000), the binary
  4205. mode is used, or else the conversions indicated are performed.
  4206.  
  4207. CHANGES FOR AZTEC:
  4208.  
  4209. Aztec opens all files in binary. Aztec also offers the "x" and "x+" modes
  4210. which open a file for writing. If the file doesn't yet exist it is created,
  4211. With "x+" the file can be read and written after opening.
  4212.  
  4213.  
  4214.  
  4215.                                 PAGE 279
  4216.  
  4217. ----------------------------------------------------------------------------
  4218.  
  4219.                              INDEX
  4220.  
  4221. ? conditional operator                          163
  4222.  
  4223. Abbreviations                                   34,195
  4224. Activate                                        237
  4225. Addresses                                       131
  4226. AND                                             165
  4227. Arguments                                       28,105,203
  4228. Arrays                                          115,189
  4229. ASCII code                                      10,84
  4230. AUTO                                            143,155,181
  4231. Aztec C                                         19,39,41,47,65,210
  4232.  
  4233. Backslash                                       29,85
  4234. <backspace> key                                 18
  4235. BASIC                                           4,48
  4236. Bitfields                                       175
  4237. Bit manipulation                                165
  4238. Bit shifting                                    167
  4239. Bit-planes                                      251
  4240. Bitwise shift operators                         167
  4241. Braces                                          25,28
  4242. BREAK                                           123
  4243. Buffer                                          206
  4244.  
  4245. C language                                      4
  4246. Calculation                                     35,61
  4247. CASE statement                                  189
  4248. CAST operator                                   71
  4249. CHAR                                            39,57,68,111,115,133,136,
  4250.                                                 181,203
  4251.  
  4252. Char pointer                                    191
  4253. Character strings.                              39
  4254. CLI                                             10,13,17,25,203,228
  4255. Comments                                        30,258
  4256. Comparison operators                            45
  4257. Compiler                                        3-5,9,27,153
  4258. Complex Data Types                              173
  4259. CON                                             219
  4260. Conditional Operator                            163
  4261. Console                                         218
  4262. Constant                                        177
  4263. CONTINUE                                        123,125
  4264. Conversion program                              82
  4265. CPU                                             206
  4266. CREATE                                          213
  4267. <ctrl><x>                                       18
  4268.  
  4269. Data types                                      105,182,231
  4270. De-referencing                                  133
  4271. Decimal notation                                85
  4272. Declarations                                    99,181
  4273. Decrement Operator                              97
  4274. DEFINE                                          174,206
  4275. Definition                                      99
  4276. Direct Access                                   216
  4277. Directives                                      229
  4278. Do ... While loop                               49,58
  4279. DOS                                             257
  4280. DOUBLE                                          67,106,136,178
  4281.  
  4282. ED                                              10,91
  4283. Editor                                          3,9
  4284. ELSE                                            33
  4285. End of Paragraph                                27
  4286. ENUM                                            177
  4287. EOF                                             209
  4288. Error Checking                                  49
  4289. Errors                                          189,196,231
  4290. <esc> key                                       18
  4291. Escape sequences                                28
  4292. EXCLUSIVE OR                                    168
  4293. EXTERN                                          99,100,145,181
  4294.  
  4295. FGETC                                           211
  4296. File extension                                  10
  4297. File mode                                       208
  4298. FLOAT                                           67,115,136,146,173,181,195
  4299. Floating point numbers                          37
  4300. Floating point variables                        67
  4301. Flowchart                                       9
  4302. FOPEN                                           209
  4303. FOR                                             48,57,123
  4304. Format Specification                            32,77
  4305. FPRINTF                                         211,220
  4306. FPUTC                                           211
  4307. FREAD                                           211
  4308. FSCANF                                          208,211
  4309. FSEEK                                           216
  4310. FTELL                                           217
  4311. Function                                        12,25,28,82,105,143,195
  4312. FWRITE                                          211
  4313.  
  4314. Gadget                                          235
  4315. GETC                                            206
  4316. GETCHAR                                         148,207,218
  4317. Global variables                                155,156
  4318. GOTO                                            169
  4319. Guru Meditation                                 37
  4320.  
  4321. Header Files                                    91,206,236
  4322. Hexadecimal system                              80,81
  4323. High Level Languages                            4
  4324.  
  4325. Icons                                           17,227,235
  4326. IF                                              32-33,45,119
  4327. Increment operator                              97
  4328. Index                                           58
  4329. Initialisation                                  99,184
  4330. INT                                             31,67,106,115,133,181,231
  4331. Integer Division                                61
  4332. Integer variables                               31
  4333. Integers                                        31
  4334. Interlace                                       252
  4335. Interpreted Languages                           4,5
  4336. Intuition                                       235,238
  4337. ITOA                                            157
  4338.  
  4339. Keywords                                        25
  4340.  
  4341. Lattice C                                       13,38,41,46,65,81,91,212
  4342. Library Macros                                  198
  4343. Library                                         25,238
  4344. Linefeeds                                       27
  4345. Linker                                          3,9,12,27
  4346. Logical AND                                     52
  4347. Logical errors                                  13
  4348. Logical OR                                      52
  4349. LOGO                                            4
  4350. LONG                                            68,69,82,115,133,181
  4351.                                                 182,217
  4352. Loops                                           45
  4353. LSEEK                                           216
  4354.  
  4355. Machine Language                                4
  4356. Macros                                          3,195,227
  4357. MAIN function                                   25,99,105,203
  4358. MAKE file                                       13,203
  4359. Menus                                           235
  4360. Modula 2                                        4
  4361. Modules                                         12
  4362. Modulo                                          61,157
  4363. Mouse                                           17,235
  4364. Multi-dimensional arrays                        117
  4365. Multiple assignment                             101
  4366. Multiple dimensions                             156
  4367. Multitasking                                    235
  4368.  
  4369. Nocarerefresh                                   237
  4370. Number Conversion                               82,86
  4371.  
  4372. Object Code                                     11
  4373. Octal system                                    80
  4374. One's complement                                168
  4375. One-dimensional arrays                          117
  4376. OPEN function                                   213,236
  4377. Operating system                                235
  4378. OR                                              166
  4379.  
  4380. Pascal                                          4,29
  4381. Pointer arrays                                  189
  4382. Pointers                                        131,133,173,189,235
  4383. Precedence                                      61,136
  4384. Preferences                                     237
  4385. PreProcessor                                    89,227,229
  4386. PreProcessor directives                         229
  4387. PRINTF                                          22,25,27,45,75,98,
  4388.                                                 124,157,189
  4389. Program format                                  27
  4390. PUTC                                            206
  4391. PUTCHAR                                         207
  4392. PUTS                                            189
  4393.  
  4394. RAW                                             220
  4395. Redirection                                     222
  4396. Referencing                                     133
  4397. Register                                        143,146,181
  4398. RETURN                                          106
  4399. <Return> key                                    18,40
  4400. Reverse                                         159
  4401.  
  4402. SCANF                                           31,75,131,134,208,218
  4403. Scanner                                         262
  4404. Screens                                         243
  4405. Semicolon                                       106
  4406. SHORT                                           68,69,181
  4407. SIZEOF                                          164,191,212
  4408. Smart_refresh                                   237
  4409. Source Code                                     28,96,189
  4410. SPRINTF                                         220
  4411. SQUARE                                          106
  4412. Standard input/output                           218
  4413. Statement Block                                 34
  4414. STATIC variables                                144,156,181
  4415. STDERR                                          223
  4416. STDIN                                           223
  4417. STDIO.H                                         91,148,163,223
  4418. STDOUT                                          223
  4419. STRCMP                                          154
  4420. STRCPY                                          109,135,147,190
  4421. Strings                                         57,178
  4422. STRLEN                                          111
  4423. STRUCT                                          173,236
  4424. Structures                                      183,235
  4425. SWITCH                                          123,125
  4426. Syntax errors                                   13
  4427. System crash                                    37
  4428.  
  4429. TELL                                            217
  4430. TEXT_ARR                                        182
  4431. Tips and tricks                                 227
  4432. Transportability                                6
  4433. Type conversion                                 70
  4434. TYPEDEF                                         178
  4435.  
  4436. Unbuffered Input / Output                       213
  4437. UNSIGNED                                        67,175,181
  4438. UNSIGNED INT                                    69
  4439. User-defined libraries                          153
  4440.  
  4441. Variable Declaration                            105
  4442. Variables                                       31,65,143,173
  4443. VOID                                            25,105,108
  4444. WHILE                                           45,83,97,98,109,123,154
  4445. Window flags                                    237
  4446. WINDOWDEPTH                                     237
  4447. WINDOWDRAG                                      237
  4448. Windows                                         235
  4449. WiINDOWSIZING                                   237
  4450. Word Processor                                  10
  4451. Workbench                                       227,228
  4452.  
  4453.  
  4454.  
  4455. * - * - * - * - * - * - * - * T H E   E N D * - * - * - * - * - * - * - *
  4456.  
  4457.  
  4458.  
  4459.            This File was Downloaded from ....... > T H E  J A M < <
  4460.  
  4461.  
  4462.            Running on A3000 (One Parted +2 Node's)
  4463.  
  4464.            Node 1 : 49(0)201-626-047      Node 2 : 49(0)201-622-897
  4465.  
  4466.            System-Operator : Selim and Rudi       Co-Operator : Oli
  4467.  
  4468.  
  4469.  
  4470.                             This file passed through
  4471.                                      __        __     __ __
  4472.                      |/\ |/\  /||_ ||  ||/\   |  | /||  || \
  4473.                      |\/ |\/ |-| |_||-| |\/   | __|-|   ||-
  4474.                      |   | \ | | __||__|| \   |__|| |  / |_/
  4475.  
  4476.  
  4477.            L S D   U N I T E D   S T A T E S   H E A D Q U A R T E R S
  4478.  
  4479.                                  (501) 336-9661
  4480.  
  4481.                          long before you ever got it... 
  4482.  
  4483.  
  4484.